Vorgehensweise: Zugriff auf einen WSE3.0-Dienst über einen WCF-Client
Windows Communication Foundation (WCF)-Clients sind auf niedriger Ebene mit Diensten von Web Services Enhancements (WSE) 3.0 für Microsoft .NET kompatibel, wenn WCF-Clients für die Verwendung der Version der WS-Addressing-Spezifikation vom August 2004 konfiguriert sind. WSE 3.0-Dienste unterstützen jedoch nicht das Metadatenaustauschprotokoll (Metadata Exchange, MEX). Wenn Sie also das ServiceModel Metadata Utility Tool (Svcutil.exe) zum Erstellen einer WCF-Clientklasse verwenden, werden die Sicherheitseinstellungen auf den generierten WCF-Client nicht angewendet. Deshalb müssen Sie die für den WSE 3.0-Dienst erforderlichen Sicherheitseinstellungen angeben, nachdem der WCF-Client generiert wurde.
Sie können diese Sicherheitseinstellungen mithilfe einer benutzerdefinierten Bindung anwenden, um die Anforderungen des WSE 3.0-Diensts und die interoperablen Anforderungen zwischen einem WSE 3.0-Dienst und einem WCF-Client zu berücksichtigen. Diese Interoperabilitätsanforderungen umfassen die oben genannte Verwendung der WS-Addressing-Spezifikation vom August 2004 und den WSE 3.0-Standardnachrichtenschutz von SignBeforeEncrypt. Der Standardnachrichtenschutz für WCF ist SignBeforeEncryptAndEncryptSignature. In diesem Thema wird erläutert, wie Sie eine WCF-Bindung erstellen, die mit einem WSE 3.0-Dienst zusammenarbeitet. WCF bietet auch ein Beispiel, das diese Bindung enthält. Weitere Informationen zu diesem Beispiel finden Sie unter Zusammenarbeit mit ASMX-Webdiensten.
So greifen Sie mit einem WCF-Client auf einen WSE 3.0-Webdienst zu
Führen Sie das ServiceModel Metadata Utility Tool (Svcutil.exe) aus, um einen WCF-Client für den WSE 3.0-Webdienst zu erstellen.
Für einen WSE 3.0-Webdienst wird ein WCF-Client erstellt. Da WSE 3.0 das MEX-Protokoll nicht unterstützt, können Sie das Tool nicht nutzen, um die Sicherheitsanforderungen für den Webdienst aufzurufen. Der Anwendungsentwickler muss die Sicherheitseinstellungen für den Client hinzufügen.
Weitere Informationen zum Erstellen eines WCF-Clients finden Sie unter Vorgehensweise: Erstellen eines Clients.
Erstellen Sie eine Klasse, die eine Bindung darstellt, die mit WSE 3.0-Webdiensten kommunizieren kann.
Die folgende Klasse gehört zum Beispiel Zusammenarbeit mit WSE:
Erstellen Sie eine von der Binding-Klasse abgeleitete Klasse.
Der folgende Code erstellt eine Klasse mit dem Namen
WseHttpBinding
, die von der Binding-Klasse abgeleitet wird.public class WseHttpBinding : Binding {
Public Class WseHttpBinding Inherits Binding
Fügen Sie Eigenschaften zur Klasse hinzu, die die sofort verwendbare WSE-Assertion festlegen, die vom WSE-Dienst verwendet wird. Hierzu gehört, ob abgeleitete Schlüssel erforderlich sind, ob Sicherheitssitzungen zum Einsatz kommen, ob Signaturbestätigungen erforderlich sind sowie die Einstellungen für den Nachrichtenschutz. In WSE 3.0 gibt eine sofort verwendbare Assertion die Sicherheitsanforderungen für einen Client oder Webdienst an – ähnlich dem Authentifizierungsmodus einer Bindung in WCF.
Das folgende Codebeispiel definiert die
SecurityAssertion
,RequireDerivedKeys
EstablishSecurityContext
und dieMessageProtectionOrder
-Eigenschaften, die die sofort verwendbare WSE-Assertion festlegen. Hierzu gehört, ob abgeleitete Schlüssel erforderlich sind, ob Sicherheitssitzungen zum Einsatz kommen, ob Signaturbestätigungen erforderlich sind sowie die Einstellungen für den Nachrichtenschutz.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
Überschreiben Sie die CreateBindingElements-Methode, um die Bindungseigenschaften einzurichten.
Das folgende Codebeispiel legt die Einstellungen für Transport, Nachrichtencodierung und Nachrichtenschutz fest, indem die Werte für
SecurityAssertion
und dieMessageProtectionOrder
-Eigenschaften abgerufen werden.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
Fügen Sie im Clientanwendungscode Code hinzu, um die Bindungseigenschaften festzulegen.
Im folgenden Codebeispiel wird angegeben, dass der WCF-Client den Nachrichtenschutz und die Authentifizierung – wie von der sofort verwendbaren WSE 3.0-Sicherheitsassertion
AnonymousForCertificate
definiert – verwenden muss. Darüber hinaus sind Sicherheitssitzungen und abgeleitete Schlüssel erforderlich.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)
Beispiel
Das folgende Codebeispiel definiert eine benutzerdefinierte Bindung, die Eigenschaften offenlegt, die mit den Eigenschaften der sofort verwendbaren WSE 3.0-Sicherheitsassertion übereinstimmen. Die benutzerdefinierte Bindung mit dem Namen WseHttpBinding
wird dann zur Angabe der Bindungseigenschaften für einen WCF-Client verwendet, der mit dem Beispiel „WSSecurityAnonymous WSE 3.0 QuickStart“ kommuniziert.