共用方式為


HOW TO:使用 WCF 用戶端來存取 WSE 3.0 服務

當 Windows Communication Foundation (WCF) 用戶端設定為使用 WS-Addressing 的 2004 年 8 月版本規格時,WCF 用戶端的連線層級會與適用 Microsoft .NET 的 Web 服務增強 (WSE) 3.0 服務相容。 不過,WSE 3.0 服務不支援中繼資料交換 (MEX) 通訊協定,當您使用 ServiceModel 中繼資料公用程式工具 (Svcutil.exe) 來建立 WCF 用戶端類別時,安全性設定不會套用至所產生的 WCF 用戶端。 因此,在產生 WCF 用戶端之後,您必須指定 WSE 3.0 服務所需的安全性設定。

您可以使用自訂繫結程序來套用這些安全性設定,將 WSE 3.0 服務的需求,以及 WSE 3.0 服務和 WCF 用戶端之間的互通需求納入考量。 這些互通性需求包含上述的 WS-Addressing August 2004 規格使用和 WSE 3.0 預設訊息保護 SignBeforeEncrypt。 WCF 的預設訊息保護為 SignBeforeEncryptAndEncryptSignature。 本主題詳細說明如何建立與 WSE 3.0 服務相互操作的 WCF 繫結。 WCF 也會提供包含這個繫結的範例。 如需此範例的詳細資訊,請參閱 與 ASMX Web 服務交互操作

若要使用 WCF 用戶端來存取 WSE 3.0 Web 服務

  1. 執行 ServiceModel 中繼資料公用程式工具 (Svcutil.exe),以為 WSE 3.0 Web 服務建立 WCF 用戶端。

    針對 WSE 3.0 Web 服務,會建立 WCF 用戶端。 因為 WSE 3.0 不支援 MEX 通訊協定,所以您無法使用此工具擷取 Web 服務的安全性需求。 應用程式開發人員必須為用戶端加入安全性設定。

    如需建立 WCF 用戶端的詳細資訊,請參閱如何:建立用戶端

  2. 建立類別,表示可與 WSE 3.0 Web 服務通訊的繫結。

    下列類別是與 WSE 交互操作範例的一部分:

    1. 建立從 Binding 類別衍生的類別。

      下列程式碼範例會建立一個名為 WseHttpBinding 的類別,此類別衍生自 Binding 類別。

      public class WseHttpBinding : Binding
      {
      
      Public Class WseHttpBinding
          Inherits Binding
      
    2. 將屬性加入至類別,這些屬性會指定 WSE 服務所使用的 WSE 通行判斷提示 (Turnkey Assertion)、是否需要衍生金鑰、是否使用安全工作階段、是否需要簽章確認,以及訊息保護設定。 在 WSE 3.0 中,周全判斷提示會指定用戶端或 Web 服務的安全性需求,這與 WCF 中的繫結程序驗證模式類似。

      下列程式碼範例會定義 SecurityAssertionRequireDerivedKeysEstablishSecurityContextMessageProtectionOrder 屬性,這些屬性會分別指定 WSE 通行判斷提示、是否需要衍生金鑰、是否使用安全工作階段、是否需要簽章確認,以及訊息保護設定。

      
      private WseSecurityAssertion assertion;
      public WseSecurityAssertion SecurityAssertion
      {
          get { return assertion; }
          set { assertion = value; }
      }
      
      private bool requireDerivedKeys;
      public bool RequireDerivedKeys
      {
          get { return requireDerivedKeys; }
          set { requireDerivedKeys = value; }
      }
      
      private bool establishSecurityContext;
      public bool EstablishSecurityContext
      {
          get { return establishSecurityContext; }
          set { establishSecurityContext = value; }
      }
      
      private bool requireSignatureConfirmation;
      public bool RequireSignatureConfirmation
      {
          get { return requireSignatureConfirmation; }
          set { requireSignatureConfirmation = value; }
      }
      
      private MessageProtectionOrder messageProtectionOrder;
      public MessageProtectionOrder MessageProtectionOrder
      {
          get { return messageProtectionOrder; }
          set { messageProtectionOrder = value; }
      }
      
      Public Property SecurityAssertion() As WseSecurityAssertion
      
          Get
      
              Return assertion
      
          End Get
          Set(ByVal value As WseSecurityAssertion)
      
              assertion = value
      
          End Set
      
      End Property
      
      Private m_requireDerivedKeys As Boolean
      Public Property RequireDerivedKeys() As Boolean
      
          Get
      
              Return m_requireDerivedKeys
      
          End Get
          Set(ByVal value As Boolean)
      
              m_requireDerivedKeys = value
      
          End Set
      
      End Property
      
      Private m_establishSecurityContext As Boolean
      Public Property EstablishSecurityContext() As Boolean
      
          Get
      
              Return m_establishSecurityContext
      
          End Get
          Set(ByVal value As Boolean)
      
              m_establishSecurityContext = value
      
          End Set
      
      End Property
      
      Private m_requireSignatureConfirmation As Boolean
      Public Property RequireSignatureConfirmation() As Boolean
      
          Get
      
              Return m_requireSignatureConfirmation
      
          End Get
          Set(ByVal value As Boolean)
      
              m_requireSignatureConfirmation = value
      
          End Set
      
      End Property
      
      Private m_messageProtectionOrder As MessageProtectionOrder
      Public Property MessageProtectionOrder() As MessageProtectionOrder
      
          Get
      
              Return m_messageProtectionOrder
      
          End Get
          Set(ByVal value As MessageProtectionOrder)
      
              m_messageProtectionOrder = value
      
          End Set
      
      End Property
      
    3. 覆寫 CreateBindingElements 方法來設定繫結屬性。

      下列程式碼範例會藉由取得 SecurityAssertionMessageProtectionOrder 屬性的值,指定傳輸、訊息編碼和訊息保護設定。

      public override BindingElementCollection CreateBindingElements()
      {
          //SecurityBindingElement sbe = bec.Find<SecurityBindingElement>();
          BindingElementCollection bec = new BindingElementCollection();
          // By default http transport is used
          SecurityBindingElement securityBinding;
          BindingElement transport;
      
          switch (assertion)
          {
              case WseSecurityAssertion.UsernameOverTransport:
                  transport = new HttpsTransportBindingElement();
                  securityBinding = (TransportSecurityBindingElement)SecurityBindingElement.CreateUserNameOverTransportBindingElement();
                  if (establishSecurityContext == true)
                      throw new InvalidOperationException("Secure Conversation is not supported for this Security Assertion Type");
                  if (requireSignatureConfirmation == true)
                      throw new InvalidOperationException("Signature Confirmation is not supported for this Security Assertion Type");
                  break;
              case WseSecurityAssertion.MutualCertificate10:
                  transport = new HttpTransportBindingElement();
                  securityBinding = SecurityBindingElement.CreateMutualCertificateBindingElement(MessageSecurityVersion.WSSecurity10WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10);
                  if (requireSignatureConfirmation == true)
                      throw new InvalidOperationException("Signature Confirmation is not supported for this Security Assertion Type");
                  ((AsymmetricSecurityBindingElement)securityBinding).MessageProtectionOrder = messageProtectionOrder;
                  break;
              case WseSecurityAssertion.UsernameForCertificate:
                  transport = new HttpTransportBindingElement();
                  securityBinding = (SymmetricSecurityBindingElement)SecurityBindingElement.CreateUserNameForCertificateBindingElement();
                  // We want signatureconfirmation on the bootstrap process
                  // either for the application messages or for the RST/RSTR
                  ((SymmetricSecurityBindingElement)securityBinding).RequireSignatureConfirmation = requireSignatureConfirmation;
                  ((SymmetricSecurityBindingElement)securityBinding).MessageProtectionOrder = messageProtectionOrder;
                  break;
              case WseSecurityAssertion.AnonymousForCertificate:
                  transport = new HttpTransportBindingElement();
                  securityBinding = (SymmetricSecurityBindingElement)SecurityBindingElement.CreateAnonymousForCertificateBindingElement();
                  ((SymmetricSecurityBindingElement)securityBinding).RequireSignatureConfirmation = requireSignatureConfirmation;
                  ((SymmetricSecurityBindingElement)securityBinding).MessageProtectionOrder = messageProtectionOrder;
                  break;
              case WseSecurityAssertion.MutualCertificate11:
                  transport = new HttpTransportBindingElement();
                  securityBinding = SecurityBindingElement.CreateMutualCertificateBindingElement(MessageSecurityVersion.WSSecurity11WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11);
                  ((SymmetricSecurityBindingElement)securityBinding).RequireSignatureConfirmation = requireSignatureConfirmation;
                  ((SymmetricSecurityBindingElement)securityBinding).MessageProtectionOrder = messageProtectionOrder;
                  break;
              case WseSecurityAssertion.Kerberos:
                  transport = new HttpTransportBindingElement();
                  securityBinding = (SymmetricSecurityBindingElement)SecurityBindingElement.CreateKerberosBindingElement();
                  ((SymmetricSecurityBindingElement)securityBinding).RequireSignatureConfirmation = requireSignatureConfirmation;
                  ((SymmetricSecurityBindingElement)securityBinding).MessageProtectionOrder = messageProtectionOrder;
                  break;
              default:
                  throw new NotSupportedException("This supplied Wse security assertion is not supported");
          }
          //Set defaults for the security binding
          securityBinding.IncludeTimestamp = true;
      
          // Derived Keys
          // set the preference for derived keys before creating SecureConversationBindingElement
          securityBinding.SetKeyDerivation(requireDerivedKeys);
      
          //Secure Conversation
          if (establishSecurityContext == true)
          {
              SymmetricSecurityBindingElement secureconversation =
                      (SymmetricSecurityBindingElement)SymmetricSecurityBindingElement.CreateSecureConversationBindingElement(
                                                  securityBinding, false);
              // This is the default
              //secureconversation.DefaultProtectionLevel = ProtectionLevel.EncryptAndSign;
      
              //Set defaults for the secure conversation binding
              secureconversation.DefaultAlgorithmSuite = SecurityAlgorithmSuite.Basic256;
              // We do not want signature confirmation on the application level messages
              // when secure conversation is enabled.
              secureconversation.RequireSignatureConfirmation = false;
              secureconversation.MessageProtectionOrder = messageProtectionOrder;
              secureconversation.SetKeyDerivation(requireDerivedKeys);
              securityBinding = secureconversation;
          }
      
          // Add the security binding to the binding collection
          bec.Add(securityBinding);
      
          // Add the message encoder.
          TextMessageEncodingBindingElement textelement = new TextMessageEncodingBindingElement();
          textelement.MessageVersion = MessageVersion.Soap11WSAddressingAugust2004;
          //These are the defaults required for WSE
          //textelement.MessageVersion = MessageVersion.Soap11Addressing1;
          //textelement.WriteEncoding = System.Text.Encoding.UTF8;
          bec.Add(textelement);
      
          // Add the transport
          bec.Add(transport);
      
          // return the binding elements
          return bec;
      }
      
      Public Overloads Overrides Function CreateBindingElements() As BindingElementCollection
      
          'SecurityBindingElement sbe = bec.Find<SecurityBindingElement>();
          Dim bec As New BindingElementCollection()
          ' By default http transport is used
          Dim securityBinding As SecurityBindingElement
          Dim transport As BindingElement
      
          Select Case assertion
      
              Case WseSecurityAssertion.UsernameOverTransport
                  transport = New HttpsTransportBindingElement()
                  securityBinding = DirectCast(SecurityBindingElement.CreateUserNameOverTransportBindingElement(), TransportSecurityBindingElement)
                  If m_establishSecurityContext = True Then
                      Throw New InvalidOperationException("Secure Conversation is not supported for this Security Assertion Type")
                  End If
                  If m_requireSignatureConfirmation = True Then
                      Throw New InvalidOperationException("Signature Confirmation is not supported for this Security Assertion Type")
                  End If
                  Exit Select
              Case WseSecurityAssertion.MutualCertificate10
                  transport = New HttpTransportBindingElement()
                  securityBinding = SecurityBindingElement.CreateMutualCertificateBindingElement(MessageSecurityVersion.WSSecurity10WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10)
                  If m_requireSignatureConfirmation = True Then
                      Throw New InvalidOperationException("Signature Confirmation is not supported for this Security Assertion Type")
                  End If
                  DirectCast(securityBinding, AsymmetricSecurityBindingElement).MessageProtectionOrder = m_messageProtectionOrder
                  Exit Select
              Case WseSecurityAssertion.UsernameForCertificate
                  transport = New HttpTransportBindingElement()
                  securityBinding = DirectCast(SecurityBindingElement.CreateUserNameForCertificateBindingElement(), SymmetricSecurityBindingElement)
                  ' We want signatureconfirmation on the bootstrap process
                  ' either for the application messages or for the RST/RSTR
                  DirectCast(securityBinding, SymmetricSecurityBindingElement).RequireSignatureConfirmation = m_requireSignatureConfirmation
                  DirectCast(securityBinding, SymmetricSecurityBindingElement).MessageProtectionOrder = m_messageProtectionOrder
                  Exit Select
              Case WseSecurityAssertion.AnonymousForCertificate
                  transport = New HttpTransportBindingElement()
                  securityBinding = DirectCast(SecurityBindingElement.CreateAnonymousForCertificateBindingElement(), SymmetricSecurityBindingElement)
                  DirectCast(securityBinding, SymmetricSecurityBindingElement).RequireSignatureConfirmation = m_requireSignatureConfirmation
                  DirectCast(securityBinding, SymmetricSecurityBindingElement).MessageProtectionOrder = m_messageProtectionOrder
                  Exit Select
              Case WseSecurityAssertion.MutualCertificate11
                  transport = New HttpTransportBindingElement()
                  securityBinding = SecurityBindingElement.CreateMutualCertificateBindingElement(MessageSecurityVersion.WSSecurity11WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11)
                  DirectCast(securityBinding, SymmetricSecurityBindingElement).RequireSignatureConfirmation = m_requireSignatureConfirmation
                  DirectCast(securityBinding, SymmetricSecurityBindingElement).MessageProtectionOrder = m_messageProtectionOrder
                  Exit Select
              Case WseSecurityAssertion.Kerberos
                  transport = New HttpTransportBindingElement()
                  securityBinding = DirectCast(SecurityBindingElement.CreateKerberosBindingElement(), SymmetricSecurityBindingElement)
                  DirectCast(securityBinding, SymmetricSecurityBindingElement).RequireSignatureConfirmation = m_requireSignatureConfirmation
                  DirectCast(securityBinding, SymmetricSecurityBindingElement).MessageProtectionOrder = m_messageProtectionOrder
                  Exit Select
              Case Else
                  Throw New NotSupportedException("This supplied Wse security assertion is not supported")
      
          End Select
      
          'Set defaults for the security binding
          securityBinding.IncludeTimestamp = True
      
          ' Derived Keys
          ' Set the preference for derived keys before creating the binding for SecureConversation.
          securityBinding.SetKeyDerivation(m_requireDerivedKeys)
      
          'Secure Conversation
          If m_establishSecurityContext = True Then
      
              Dim secureconversation As SymmetricSecurityBindingElement = DirectCast(SymmetricSecurityBindingElement.CreateSecureConversationBindingElement(securityBinding, False), SymmetricSecurityBindingElement)
              ' This is the default
              'secureconversation.DefaultProtectionLevel = ProtectionLevel.EncryptAndSign;
      
              'Set defaults for the secure conversation binding
              secureconversation.DefaultAlgorithmSuite = SecurityAlgorithmSuite.Basic256
              ' We do not want signature confirmation on the application level messages
              ' when secure conversation is enabled.
              secureconversation.RequireSignatureConfirmation = False
              secureconversation.MessageProtectionOrder = m_messageProtectionOrder
              secureconversation.SetKeyDerivation(m_requireDerivedKeys)
              securityBinding = secureconversation
      
          End If
      
          ' Add the security binding to the binding collection
          bec.Add(securityBinding)
      
          ' Add the message encoder.
          Dim textelement As New TextMessageEncodingBindingElement()
          textelement.MessageVersion = System.ServiceModel.Channels.MessageVersion.Soap11WSAddressingAugust2004
          'These are the defaults required for WSE
          'textelement.MessageVersion = MessageVersion.Soap11Addressing1;
          'textelement.WriteEncoding = System.Text.Encoding.UTF8;
          bec.Add(textelement)
      
          ' Add the transport
          bec.Add(transport)
      
          ' return the binding elements
          Return bec
      
      End Function
      
  3. 在用戶端應用程式程式碼中,加入程式碼以設定繫結屬性。

    下列程式碼範例會指定 WCF 用戶端必須依照 WSE 3.0 AnonymousForCertificate 周全的安全性判斷提示所定義,使用訊息保護和驗證。 此外,也需要安全工作階段和衍生金鑰。

    static void CallWseService(bool usePolicyFile)
    {
        EndpointAddress address = new EndpointAddress(new Uri("http://localhost/WSSecurityAnonymousPolicy/WSSecurityAnonymousService.asmx"),
                                                      EndpointIdentity.CreateDnsIdentity("WSE2QuickStartServer"));
    
        WseHttpBinding binding = new WseHttpBinding();
        if (!usePolicyFile)
        {
            binding.SecurityAssertion = WseSecurityAssertion.AnonymousForCertificate;
            binding.EstablishSecurityContext = true;
            binding.RequireDerivedKeys = true;
            binding.MessageProtectionOrder = MessageProtectionOrder.SignBeforeEncrypt;
        }
        else
        {
            binding.LoadPolicy("..\\wse3policyCache.config", "ServerPolicy");
        }
    
        WSSecurityAnonymousServiceSoapClient client = new WSSecurityAnonymousServiceSoapClient(binding, address);
    
    Private Shared Sub CallWseService(ByVal usePolicyFile As Boolean)
    
        Dim address As New EndpointAddress(New Uri("http://localhost/WSSecurityAnonymousPolicy/WSSecurityAnonymousService.asmx"), EndpointIdentity.CreateDnsIdentity("WSE2QuickStartServer"))
    
        Dim binding As New WseHttpBinding()
        If Not usePolicyFile Then
    
            binding.SecurityAssertion = WseSecurityAssertion.AnonymousForCertificate
            binding.EstablishSecurityContext = True
            binding.RequireDerivedKeys = True
            binding.MessageProtectionOrder = MessageProtectionOrder.SignBeforeEncrypt
    
        Else
            binding.LoadPolicy("..\wse3policyCache.config", "ServerPolicy")
        End If
    
        Dim client As New WSSecurityAnonymousServiceSoapClient(binding, address)
    

範例

下列程式碼範例會定義自訂的繫結,此繫結會公開 WSE 3.0 通行安全性判斷提示屬性的對應屬性。 此自訂繫結,名為 WseHttpBinding,接著會用來指定可與 WSSecurityAnonymous WSE 3.0 快速入門範例通訊的 WCF 用戶端的繫結屬性。

另請參閱