作法:保護中繼資料端點的安全

服務的中繼資料可能包含有關應用程式而可能會遭到惡意使用者利用的敏感資訊。 服務的取用者也可能會要求安全機制來取得關於服務的中繼資料。 因此,有時候會需要使用安全端點來發行中繼資料。

為了保護應用程式端點,通常會以 Windows Communication Foundation (WCF) 中所定義的標準安全性機制來保護中繼資料端點。 如需詳細資訊,請參閱安全性概觀

本主題會逐步解說建立受 Secure Sockets Layer (SSL) 憑證保護之端點 (也就是 HTTPS 端點) 的步驟。

在程式碼中建立安全的 HTTPS GET 中繼資料端點

  1. 使用適當的 X.509 憑證設定連接埠。 憑證必須來自受信任的授權單位 (CA),而且必須可以用於「服務授權」。您必須使用 HttpCfg.exe 工具將憑證附加到該連接埠。 請參閱操作說明:使用 SSL 憑證設定連接埠

    重要

    憑證的主體或是其網域名稱系統 (DNS) 必須符合電腦的名稱。 這點是必要條件,因為 HTTPS 機制一開始執行的一個步驟,就是檢查該憑證是否為發行給與其被叫用位址相同的統一資源識別元 (URI)。

  2. 建立 ServiceMetadataBehavior 類別的新執行個體。

  3. HttpsGetEnabled 類別的 ServiceMetadataBehavior 屬性設定為 true

  4. HttpsGetUrl 屬性設定為適當的 URL。 請注意,若您指定絕對位址,則 URL 的開頭就必須是 https:// 配置。 如果是指定相對位址,您就必須提供服務主機的 HTTPS 起始位址。 如果沒有設定這個屬性,預設的位址就會是 "",或是直接使用服務的 HTTPS 起始位址。

  5. Behaviors 類別之 ServiceDescription 屬性所傳回的行為集合中新增執行個體,如下列程式碼所示。

    // Create a new metadata behavior object and set its properties to
    // create a secure endpoint.
    ServiceMetadataBehavior sb = new ServiceMetadataBehavior();
    sb.HttpsGetEnabled = true;
    sb.HttpsGetUrl = new Uri("https://myMachineName:8036/myEndpoint");
    myServiceHost.Description.Behaviors.Add(sb);
    
    myServiceHost.Open();
    
    ' Create a new metadata behavior object and set its properties to 
    ' create a secure endpoint. 
    Dim sb As New ServiceMetadataBehavior()
    
    With sb
        .HttpsGetEnabled = True
        .HttpsGetUrl = New Uri("https://myMachineName:8036/myEndpoint")
    End With
    
    With myServiceHost
        .Description.Behaviors.Add(sb)
        .Open()
    End With
    

在組態中建立安全的 HTTPS GET 中繼資料端點

  1. <behaviors> 元素新增至服務組態檔的 <system.serviceModel> 元素。

  2. <serviceBehaviors> 元素新增至 <behaviors> 元素。

  3. <behavior> 元素新增至 <serviceBehaviors> 元素。

  4. name 項目的 <behavior> 屬性設定為適當的值。 name 屬性 (Attribute) 是必要項。 下面這個範例會使用值 mySvcBehavior

  5. <serviceMetadata> 新增至 <behavior> 元素。

  6. httpsGetEnabled 項目的 <serviceMetadata> 屬性設定為 true

  7. httpsGetUrl 項目的 <serviceMetadata> 屬性設定為適當的值。 請注意,若您指定絕對位址,則 URL 的開頭就必須是 https:// 配置。 如果是指定相對位址,您就必須提供服務主機的 HTTPS 起始位址。 如果沒有設定這個屬性,預設的位址就會是 "",或是直接使用服務的 HTTPS 起始位址。

  8. 若要搭配服務一起使用此行為,請將 <service> 元素的 behaviorConfiguration 屬性設定為此行為元素之名稱屬性的值。 下列組態程式碼會示範完整的範例。

    <?xml version="1.0" encoding="utf-8" ?>
    <configuration>
     <system.serviceModel>
      <behaviors>
       <serviceBehaviors>
        <behavior name="mySvcBehavior">
         <serviceMetadata httpsGetEnabled="true"
              httpsGetUrl="https://localhost:8036/calcMetadata" />
        </behavior>
       </serviceBehaviors>
      </behaviors>
     <services>
      <service behaviorConfiguration="mySvcBehavior"
            name="Microsoft.Security.Samples.Calculator">
       <endpoint address="http://localhost:8037/ServiceModelSamples/calculator"
       binding="wsHttpBinding" bindingConfiguration=""
       contract="Microsoft.Security.Samples.ICalculator" />
      </service>
     </services>
    </system.serviceModel>
    </configuration>
    

範例

下列範例會建立 ServiceHost 類別的執行個體,並新增端點。 接下來,這段程式碼會建立 ServiceMetadataBehavior 類別的執行個體,並設定其中屬性來建立安全的中繼資料交換點。

WSHttpBinding myBinding = new WSHttpBinding();
myBinding.Security.Mode = SecurityMode.Message;
myBinding.Security.Message.ClientCredentialType =
    MessageCredentialType.Windows;

// Create the Type instances for later use and the URI for
// the base address.
Type contractType = typeof(ICalculator);
Type serviceType = typeof(Calculator);
Uri baseAddress = new
    Uri("http://localhost:8037/serviceModelSamples/");

// Create the ServiceHost and add an endpoint.
ServiceHost myServiceHost =
    new ServiceHost(serviceType, baseAddress);
myServiceHost.AddServiceEndpoint
    (contractType, myBinding, "secureCalculator");
// Create a new metadata behavior object and set its properties to
// create a secure endpoint.
ServiceMetadataBehavior sb = new ServiceMetadataBehavior();
sb.HttpsGetEnabled = true;
sb.HttpsGetUrl = new Uri("https://myMachineName:8036/myEndpoint");
myServiceHost.Description.Behaviors.Add(sb);

myServiceHost.Open();
// Use the GetHostEntry method to return the actual machine name.
string machineName = System.Net.Dns.GetHostEntry("").HostName ;
Console.WriteLine("Listening @ {0}:8037/serviceModelSamples/", machineName);
Console.WriteLine("Press Enter to close the service");
Console.ReadLine();
myServiceHost.Close();
Dim myBinding As New WSHttpBinding()
With myBinding.Security
    .Mode = SecurityMode.Message
    .Message.ClientCredentialType = MessageCredentialType.Windows
End With

' Create the Type instances for later use and the URI for 
' the base address.
Dim contractType = GetType(ICalculator)
Dim serviceType = GetType(Calculator)
Dim baseAddress As New Uri("http://localhost:8037/serviceModelSamples/")

' Create the ServiceHost and add an endpoint. 
Dim myServiceHost As New ServiceHost(serviceType, baseAddress)
myServiceHost.AddServiceEndpoint(contractType, myBinding, "secureCalculator")

' Create a new metadata behavior object and set its properties to 
' create a secure endpoint. 
Dim sb As New ServiceMetadataBehavior()

With sb
    .HttpsGetEnabled = True
    .HttpsGetUrl = New Uri("https://myMachineName:8036/myEndpoint")
End With

With myServiceHost
    .Description.Behaviors.Add(sb)
    .Open()
End With

' Use the GetHostEntry method to return the actual machine name.
Dim machineName = System.Net.Dns.GetHostEntry("").HostName
Console.WriteLine("Listening @ {0}:8037/serviceModelSamples/", machineName)
Console.WriteLine("Press Enter to close the service")
Console.ReadLine()
myServiceHost.Close()

編譯程式碼

此程式碼範例會使用下列命名空間 (Namespace):

另請參閱