Поделиться через


Как настраивать клиент WCF для взаимодействия со службами WSE 3.0

Клиенты Windows Communication Foundation (WCF) на уровне линий связи совместимы со службами расширений веб-служб версии 3.0 для Microsoft .NET (WSE), если клиенты WCF настроены на использование спецификации WS-Addressing версии августа 2004 г.

Настройка клиента WCF для взаимодействия с веб-службой WSE 3.0

  1. Запустите средство Служебное средство ServiceModel Metadata Utility Tool (Svcutil.exe), чтобы создать клиент WCF для веб-службы WSE 3.0.

    Для веб-службы WSE создается класс клиента WCF.

    Сведения о создании клиента WCF см. в разделе Как создать клиент Windows Communication Foundation.

  2. Создайте класс, представляющий привязку, которая может обмениваться данными с веб-службами WSE 3.0.

    Следующий класс является частью примера Interoperating with WSE.

    1. Создайте класс, наследуемый от класса Binding.

      В следующем примере кода создается класс с именем WseHttpBinding, наследуемый от класса Binding.

      Public Class WseHttpBinding
          Inherits Binding
      
      public class WseHttpBinding : Binding
      {
      
    2. Добавьте в класс свойства, задающие готовое к использованию утверждение WSE, требуются ли производные ключи, используются ли безопасные сеансы, требуется ли подтверждение подписей, и параметры защиты сообщений.

      В следующем примере кода определяются свойства SecurityAssertion, RequireDerivedKeys, EstablishSecurityContext, MessageProtectionOrder, задающие готовое к использованию утверждение WSE, требуются ли производные ключи, используются ли безопасные сеансы, требуется ли подтверждение подписей, и задают параметры защиты сообщений соответственно.

      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
      
      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; }
      }
      
    3. Переопределите метод CreateBindingElements для задания свойств привязки.

      В следующем примере кода транспорт, кодирование сообщений и параметры защиты сообщений задаются получением значений свойств SecurityAssertion и MessageProtectionOrder.

      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
      
      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;
      }
      
  3. В коде клиентского приложения добавьте код для задания свойств привязки.

    В следующем примере кода указывается, что клиент WCF должен использовать защиту сообщений и проверку подлинности в соответствии с готовым к использованию утверждением безопасности WSE 3.0 AnonymousForCertificate. Кроме того, требуются безопасные сеансы и производные ключи.

    Private Shared Sub CallWseService(ByVal usePolicyFile As Boolean)
    
        Dim address As New EndpointAddress(New Uri("https://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)
    
    static void CallWseService(bool usePolicyFile)
    {
        EndpointAddress address = new EndpointAddress(new Uri("https://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);
    

Пример

В следующем примере кода определяется пользовательская привязка, предоставляющая свойства, соответствующие свойствам готового к использованию утверждения безопасности WSE 3.0. Затем пользовательская привязка с именем WseHttpBinding используется для задания свойств привязки для клиента WCF.

Imports System
Imports System.Collections.Generic
Imports System.Text
Imports System.Security.Cryptography.X509Certificates
Imports System.ServiceModel
Imports System.ServiceModel.Security
Imports System.ServiceModel.Channels
Imports Microsoft.VisualBasic

Namespace Microsoft.ServiceModel.Samples

    ' The service contract is defined in generatedClient.vb, generated from the service by

    ' the svcutil tool.
    Class Program

        Public Shared Sub Main(ByVal args As String())

            CallWseService(True)

        End Sub

        Private Shared Sub CallWseService(ByVal usePolicyFile As Boolean)

            Dim address As New EndpointAddress(New Uri("https://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)

            ' Need to supply the credentials depending on the type of WseSecurityAssertion used.
            ' Anonymous only requires server certificate. UsernameForCertificate would also require
            ' a username and password to be supplied.
            client.ClientCredentials.ServiceCertificate.SetDefaultCertificate(StoreLocation.LocalMachine, StoreName.My, X509FindType.FindBySubjectDistinguishedName, "CN=WSE2QuickStartServer")
            Dim symbols As String() = New String() {"FABRIKAM", "CONTOSO"}
            Dim quotes As StockQuote() = client.StockQuoteRequest(symbols)

            client.Close()

            ' Success!
            For Each quote As StockQuote In quotes

                Console.WriteLine("")
                Console.WriteLine("Symbol: " + quote.Symbol)
                Console.WriteLine("" & Chr(9) & "Name:" & Chr(9) & "" & Chr(9) & "" & Chr(9) & "" + quote.Name)
                Console.WriteLine("" & Chr(9) & "Last Price:" & Chr(9) & "" & Chr(9) & "" & quote.Last)
                Console.WriteLine("" & Chr(9) & "Previous Change:" & Chr(9) & "" & quote.PreviousChange & "%")

            Next

            Console.WriteLine("Press <ENTER> to terminate client.")
            Console.ReadLine()

        End Sub

    End Class

End Namespace
using System;
using System.Collections.Generic;
using System.Text;
using System.Security.Cryptography.X509Certificates;
using System.ServiceModel;
using System.ServiceModel.Security;
using System.ServiceModel.Channels;

namespace Microsoft.ServiceModel.Samples
{
    // The service contract is defined in generatedClient.cs, generated from the service by
    // the svcutil tool.

    class Program
    {
        static void Main(string[] args)
        {
            CallWseService(true);
        }
        static void CallWseService(bool usePolicyFile)
        {
            EndpointAddress address = new EndpointAddress(new Uri("https://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);

            // Need to supply the credentials depending on the type of WseSecurityAssertion used.
            // Anonymous only requires server certificate. UsernameForCertificate would also require
            // a username and password to be supplied.
            client.ClientCredentials.ServiceCertificate.SetDefaultCertificate(
                                                                 StoreLocation.LocalMachine,
                                                                 StoreName.My,
                                                                 X509FindType.FindBySubjectDistinguishedName,
                                                                 "CN=WSE2QuickStartServer");
            string[] symbols = new string[] { "FABRIKAM", "CONTOSO" };
            StockQuote[] quotes = client.StockQuoteRequest(symbols);

            client.Close();

            // Success!
            foreach (StockQuote quote in quotes)
            {
                Console.WriteLine("");
                Console.WriteLine("Symbol: " + quote.Symbol);
                Console.WriteLine("\tName:\t\t\t" + quote.Name);
                Console.WriteLine("\tLast Price:\t\t" + quote.Last);
                Console.WriteLine("\tPrevious Change:\t" + quote.PreviousChange + "%");
            }

            Console.WriteLine("Press <ENTER> to terminate client.");
            Console.ReadLine();
        }
    }
}

См. также

Справочник

Binding

Другие ресурсы

Interoperating with WSE