方法 : WCF クライアントで WSE 3.0 サービスにアクセスする
Windows Communication Foundation (WCF) クライアントが 2004 年 8 月版 WS-Addressing 仕様を使用して構成されている場合は、WCF クライアントに、Web Services Enhancements (WCF) 3.0 for Microsoft .NET サービスとのネットワーク レベルの互換性があります。 ただし、WSE 3.0 サービスでは、メタデータ交換 (MEX) プロトコルがサポートされていないため、ServiceModel メタデータ ユーティリティ ツール (Svcutil.exe) を使用して WCF クライアント クラスを作成すると、生成された WCF クライアントにセキュリティ設定が適用されません。 そのため、WCF クライアントの生成後に、WSE 3.0 サービスで必要なセキュリティ設定を指定する必要があります。
カスタム バインディングを使用してこれらのセキュリティ設定を適用することにより、WSE 3.0 サービスの要件、および WSE 3.0 サービスと WCF クライアントとの相互運用性の要件を考慮に入れることができます。 これらの相互運用性要件には、前述の 2004 年 8 月版 WS-Addressing 仕様の使用と、WSE 3.0 の既定のメッセージ保護が SignBeforeEncrypt であることが含まれます。 WCF の既定のメッセージ保護は、SignBeforeEncryptAndEncryptSignature です。 このトピックでは、WSE 3.0 サービスと相互運用する WCF バインディングの作成方法について詳しく説明します。 WCF には、このバインディングが組み込まれたサンプルも用意されています。 このサンプルの詳細については、「ASMX Web サービスとの相互運用性」を参照してください。
WCF クライアントで WSE 3.0 サービスにアクセスするには
ServiceModel メタデータ ユーティリティ ツール (Svcutil.exe) を実行して、WSE 3.0 Web サービス用の WCF クライアントを作成します。
WSE 3.0 Web サービスに対して、WCF クライアントが作成されます。 WSE 3.0 は MEX プロトコルをサポートしていないため、このツールを使用して Web サービスのセキュリティ要件を取得することはできません。 アプリケーション開発者は、クライアントのセキュリティ設定を追加する必要があります。
WCF クライアントの作成の詳細については、クライアントの作成方法に関するページを参照してください。
WSE 3.0 Web サービスと通信できるバインディングを表すクラスを作成します。
次のクラスは、SE との相互運用性のサンプルに含まれています。
Binding クラスから派生するクラスを作成します。
WseHttpBinding
クラスから派生する、Binding という名前のクラスを作成する方法を次のコード例に示します。public class WseHttpBinding : Binding {
Public Class WseHttpBinding Inherits Binding
WSE サービスで使用する WSE 設定不要アサーション、派生キーが必要かどうか、セキュリティで保護されたセッションを使用するかどうか、署名の確認が必要かどうか、およびメッセージ保護設定を指定するプロパティを、このクラスに追加します。 WSE 3.0 では、設定不要アサーションによって、クライアントまたは Web サービスのセキュリティ要件が指定されます。これらは、WCF のバインディングの認証モードに似ています。
WSE 設定不要アサーション、派生キーが必要かどうか、セキュリティで保護されたセッションを使用するかどうか、署名の確認が必要かどうか、およびメッセージ保護設定をそれぞれ指定する、
SecurityAssertion
、RequireDerivedKeys
、EstablishSecurityContext
、およびMessageProtectionOrder
の各プロパティを定義するコード例を次に示します。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
CreateBindingElements メソッドをオーバーライドして、バインディング プロパティを設定します。
SecurityAssertion
プロパティとMessageProtectionOrder
プロパティの値を取得することで、トランスポート、メッセージ エンコーディング、メッセージ保護設定を指定するコード例を次に示します。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
クライアントのアプリケーション コードでは、コードを追加してバインディングのプロパティを設定します。
次のコード例では、WSE 3.0
AnonymousForCertificate
の設定不要なセキュリティ アサーションで定義されているように、WCF クライアントでメッセージの保護と認証を使用しなければならないことが指定されます。 また、セキュリティで保護されたセッションと派生キーが必要です。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 QuickStart のサンプルと通信する WCF クライアントのバインディング プロパティの指定に使用されます。