共用方式為


WCF 安全性程式設計

本主題描述用來建立安全 Windows Communication Foundation (WCF) 應用程式的基本程式設計工作。 本主題僅涵蓋驗證、機密性與完整性 (統稱為「傳輸安全性」)。 本主題並未涵蓋授權 (對資源或服務的存取控制);如需授權的資訊,請參閱授權

注意

如需安全性概念的重要簡介 (特別是關於 WCF),請參閱 MSDN 上 Web Services Enhancements (WSE) 3.0 的情節、模式和實作指引中的模式組與做法教學課程。

WCF 安全性的程式設計是以設定下列項目的三個步驟為基礎:安全性模式、用戶端認證類型,以及認證值。 您可以透過程式碼或組態執行這些步驟。

設定安全性模式

以下說明 WCF 安全性模式設計程式的一般步驟:

  1. 針對應用程式需求選取一項適合的預先定義繫結程序。 如需繫結選擇清單,請參閱系統提供的繫結。 根據預設,幾乎所有的繫結都會啟用安全性。 唯一的例外是 BasicHttpBinding 類別 (使用組態時,則為 <basicHttpBinding>)。

    您選取的繫結將決定傳輸方式。 例如,WSHttpBinding 會使用 HTTP 做為傳輸方式;而 NetTcpBinding 則使用 TCP。

  2. 選取其中一項安全性模式來進行繫結。 請注意,您選取的繫結會決定可用的模式選項有哪些。 例如,WSDualHttpBinding 不允許使用傳輸安全性 (未包含在選項中)。 同樣地,MsmqIntegrationBindingNetNamedPipeBinding 也都不允許使用訊息安全性。

    您有下列三個選擇:

    1. Transport

      傳輸安全性將視您選取之繫結所使用的機制而定。 例如,假使您使用 WSHttpBinding,則安全性機制為安全通訊端層 (SSL) (同時也是 HTTPS 通訊協定的機制)。 一般來說,傳輸安全性的主要優點在於,不管您使用哪種傳輸機制,都能提供良好的輸送量。 但是,它有兩項限制:首先就是傳輸機制會指出用來驗證使用者的認證類型。 只有當服務需要與其他要求不同認證類型的服務交互操作時,這個限制才會成為缺點。 第二個限制是,由於訊息層級並未套用安全性,所以會以躍點方式 (而不是以端對端方式) 來實作安全性。 只有當用戶端與服務之間的訊息路徑包含媒介時,第二個限制才會成為問題。 如需使用哪個傳輸的詳細資訊,請參閱選擇傳輸。 如需使用傳輸安全性的詳細資訊,請參閱傳輸安全性概觀

    2. Message

      訊息安全性表示每則訊息都包含保護訊息安全的必要標頭與資料。 由於標頭的組成份子各有不同,因此您可以加入任何數量的認證。 如果您正與其他需要特定認證類型 (但無法適用傳輸機制) 的服務進行交互操作,或是如果訊息必須與一個以上的服務搭配使用,而其中每個服務需要不同的認證類型時,這項特性就會變成一個要件。

      如需詳細資訊,請參閱訊息安全性

    3. TransportWithMessageCredential

      這項選擇使用傳輸層來保護訊息傳輸的安全,而每則訊息則包含其他服務所需的豐富認證。 這項選擇會將傳輸安全性的效能優點,與訊息安全性的豐富認證優勢加以結合。 您可透過下列繫結來獲得這項優勢:BasicHttpBindingWSFederationHttpBindingNetPeerTcpBindingWSHttpBinding

  3. 如果您決定在 HTTP 上使用傳輸安全性 (亦即,HTTPS),必須同時使用 SSL 憑證來設定主機,並啟用連接埠上的 SSL。 如需詳細資訊,請參閱 HTTP 傳輸安全性

  4. 如果您正在使用 WSHttpBinding 而且不需要建立安全工作階段,請將 EstablishSecurityContext 屬性設為 false

    當用戶端與服務透過對稱金鑰來建立通道時,就會產生安全工作階段 (用戶端與伺服器都會在對話期間全程使用相同的金鑰,直到對話結束為止)。

設定用戶端認證類型

視需要選取用戶端認證類型。 如需詳細資訊,請參閱選取認證類型。 下列為可用的用戶端認證類型:

  • Windows

  • Certificate

  • Digest

  • Basic

  • UserName

  • NTLM

  • IssuedToken

視模式的設定方式而定,您必須設定認證類型。 例如,如果您選取了 wsHttpBinding,並將模式設為 [訊息],則也可以將 Message 項目的 clientCredentialType 屬性設為下列其中一個值:NoneWindowsUserNameCertificateIssuedToken,如下列組態範例所示。

<system.serviceModel>  
<bindings>  
  <wsHttpBinding>  
    <binding name="myBinding">  
      <security mode="Message"/>  
      <message clientCredentialType="Windows"/>  
    </binding>
  </wsHttpBinding>
</bindings>  
</system.serviceModel>  

或在程式碼中:

WSHttpBinding b = new WSHttpBinding();
b.Name = "myBinding";
b.Security.Mode = SecurityMode.Message;
b.Security.Message.ClientCredentialType=MessageCredentialType.Windows;
Dim b As New WSHttpBinding()
b.Name = "myBinding"
b.Security.Mode = SecurityMode.Message
b.Security.Message.ClientCredentialType = MessageCredentialType.Windows

設定服務認證值

一旦您選取了用戶端認證類型,就必須設定實際認證以供服務與用戶端使用。 在服務上,認證需透過 ServiceCredentials 類別來加以設定,並由 Credentials 類別的 ServiceHostBase 屬性傳回。 使用中的繫結意指服務認證類型、選擇的安全性模式,以及用戶端認證類型。 下列程式碼將為服務認證設定憑證。

// Create the binding for an endpoint.
NetTcpBinding b = new NetTcpBinding();
b.Security.Mode = SecurityMode.Message;

// Create the ServiceHost for a calculator.
Uri baseUri = new Uri("net.tcp://MachineName/tcpBase");
Uri[] baseAddresses = new Uri[] { baseUri };
ServiceHost sh = new ServiceHost(typeof(Calculator), baseAddresses);

// Add an endpoint using the binding and a new address.
Type c = typeof(ICalculator);
sh.AddServiceEndpoint(c, b, "MyEndpoint");

// Set a certificate as the credential for the service.
sh.Credentials.ServiceCertificate.SetCertificate(
    StoreLocation.LocalMachine,
    StoreName.My,
    X509FindType.FindBySubjectName,
    "client.com");
try
{
    sh.Open();
    Console.WriteLine("Listening....");
    Console.ReadLine();
    sh.Close();
}
catch (CommunicationException ce)
{
    Console.WriteLine("A communication error occurred: {0}", ce.Message);
    Console.WriteLine();
}
catch (System.Exception exc)
{
    Console.WriteLine("An unforeseen error occurred: {0}", exc.Message);
    Console.ReadLine();
}
' Create the binding for an endpoint.
Dim b As New NetTcpBinding()
b.Security.Mode = SecurityMode.Message

' Create the ServiceHost for a calculator.
Dim baseUri As New Uri("net.tcp://MachineName/tcpBase")
Dim baseAddresses() As Uri = {baseUri}
Dim sh As New ServiceHost(GetType(Calculator), baseAddresses)

' Add an endpoint using the binding and a new address.
Dim c As Type = GetType(ICalculator)
sh.AddServiceEndpoint(c, b, "MyEndpoint")

' Set a certificate as the credential for the service.
sh.Credentials.ServiceCertificate.SetCertificate( _
                StoreLocation.LocalMachine, _
                StoreName.My, _
                X509FindType.FindBySubjectName, _
                "contoso.com")
Try
    sh.Open()
    Console.WriteLine("Listening....")
    Console.ReadLine()
    sh.Close()
Catch ce As CommunicationException
    Console.WriteLine("A communication error occurred: {0}", ce.Message)
    Console.WriteLine()
Catch exc As System.Exception
    Console.WriteLine("An unforeseen error occurred: {0}", exc.Message)
    Console.ReadLine()
End Try

設定用戶端認證值

在用戶端上,用戶端認證值是使用 ClientCredentials 類別進行設定,並由 ClientCredentials 類別的 ClientBase<TChannel> 屬性傳回。 下列程式碼將透過 TCP 通訊協定在用戶端上將憑證設為認證。

// Create a NetTcpBinding and set its security properties. The
// security mode is Message, and the client must be authenticated with
// Windows. Therefore the client must be on the same Windows domain.
NetTcpBinding b = new NetTcpBinding();
b.Security.Mode = SecurityMode.Message;
b.Security.Message.ClientCredentialType = MessageCredentialType.Windows;

// Set a Type variable for use when constructing the endpoint.
Type c = typeof(ICalculator);

// Create a base address for the service.
Uri tcpBaseAddress =
    new Uri("net.tcp://machineName.Domain.Contoso.com:8036/serviceName");
// The base address is in an array of URI objects.
Uri[] baseAddresses = new Uri[] { tcpBaseAddress };
// Create the ServiceHost with type and base addresses.
ServiceHost sh = new ServiceHost(typeof(CalculatorClient), baseAddresses);

// Add an endpoint to the service using the service type and binding.
sh.AddServiceEndpoint(c, b, "");
sh.Open();
string address = sh.Description.Endpoints[0].ListenUri.AbsoluteUri;
Console.WriteLine("Listening @ {0}", address);
Console.WriteLine("Press enter to close the service");
Console.ReadLine();
' Create a NetTcpBinding and set its security properties. The
' security mode is Message, and the client must be authenticated with
' Windows. Therefore the client must be on the same Windows domain.
Dim b As New NetTcpBinding()
b.Security.Mode = SecurityMode.Message
b.Security.Message.ClientCredentialType = MessageCredentialType.Windows

' Set a Type variable for use when constructing the endpoint.
Dim c As Type = GetType(ICalculator)

' Create a base address for the service.
Dim tcpBaseAddress As New Uri("net.tcp://machineName.Domain.Contoso.com:8036/serviceName")
' The base address is in an array of URI objects.
Dim baseAddresses() As Uri = {tcpBaseAddress}
' Create the ServiceHost with type and base addresses.
Dim sh As New ServiceHost(GetType(CalculatorClient), baseAddresses)

' Add an endpoint to the service using the service type and binding.
sh.AddServiceEndpoint(c, b, "")
sh.Open()
Dim address As String = sh.Description.Endpoints(0).ListenUri.AbsoluteUri
Console.WriteLine("Listening @ {0}", address)
Console.WriteLine("Press enter to close the service")
Console.ReadLine()

另請參閱