チュートリアル: カスタム クライアントおよびサービスの資格情報を作成する
このトピックでは、クライアントおよびサービスにカスタム資格情報を実装する方法と、これをアプリケーション コードから使用する方法について説明します。
資格情報拡張クラス
ClientCredentials クラスおよび ServiceCredentials クラスは、Windows Communication Foundation (WCF) セキュリティ拡張のメイン エントリ ポイントです。 これらの資格情報クラスでは、アプリケーション コードから資格情報を設定し、資格情報の種類をセキュリティ トークンに変換する API を提供します ("セキュリティ トークン" とは、SOAP メッセージ内の資格情報を送信するために使用される形式です)。これらの資格情報クラスの役割は、次の 2 つの領域に分けることができます。
アプリケーションで資格情報を設定するための API を提供します。
SecurityTokenManager 実装のファクトリとして動作します。
WCF で提供される既定の実装では、システム指定の資格情報の種類をサポートし、これらの資格情報の種類を処理できるセキュリティ トークン マネージャーを作成します。
カスタマイズする理由
クライアントまたはサービスの資格情報クラスをカスタマイズする場合、いくつかの理由があります。 最大の理由として、システム指定の資格情報の種類の処理について、特に以下の必要性が生じたために WCF の既定のセキュリティ動作を変更する必要があることが挙げられます。
他の拡張ポイントを使用した場合には不可能な変更
新しい資格情報の種類の追加
新しいカスタム セキュリティ トークンの種類の追加
このトピックでは、カスタムのクライアント資格情報およびサービス資格情報を実装する方法と、これをアプリケーション コードから使用する方法について説明します。
最初の手順
カスタム資格情報クラスを作成することは、最初の手順にすぎません。なぜなら、資格情報のプロビジョニング、セキュリティ トークンのシリアル化、または認証に関する WCF の動作を変更することが、資格情報をカスタマイズする理由だからです。 このセクションの他のトピックでは、カスタムのシリアライザーと認証システムを作成する方法について説明します。 カスタム資格情報クラスの作成は、このような観点からすると、一連のトピックの最初の手順になります。 これに続く処理 (カスタムのシリアライザーおよび認証システムの作成) は、カスタム資格情報の作成後にのみ可能になります。 このトピックに基づく他のトピックには、次のものがあります。
手順
カスタム クライアント資格情報を実装するには
ClientCredentials クラスから派生する新しいクラスを定義します。
任意。 新しい資格情報の種類に新しいメソッドまたはプロパティを追加します。 新しい資格情報の種類を追加しない場合は、この手順を省略します。 次の例では、
CreditCardNumber
プロパティを追加します。CreateSecurityTokenManager メソッドをオーバーライドします。 カスタム クライアント資格情報が使用されると、WCF セキュリティ インフラストラクチャによってこのメソッドが自動的に呼び出されます。 このメソッドは、SecurityTokenManager クラスの実装のインスタンスを作成して返す役割を担います。
重要
カスタム セキュリティ トークン マネージャーを作成するために、CreateSecurityTokenManager メソッドがオーバーライドされることに注意する必要があります。 ClientCredentialsSecurityTokenManager から派生したセキュリティ トークン マネージャーは、実際のセキュリティ トークンを作成するために、SecurityTokenProvider から派生したカスタム セキュリティ トークン プロバイダーを返す必要があります。 このパターンに従ってセキュリティ トークンを作成しないと、ChannelFactory オブジェクトがキャッシュされたとき (これは、WCF クライアント プロキシの既定の動作です)、権限の昇格攻撃を受ける可能性があり、アプリケーションが正常に機能しない場合があります。 カスタム資格情報オブジェクトは、ChannelFactory の一部としてキャッシュされます。 ただし、カスタム SecurityTokenManager がすべての呼び出し時に作成され、これにより、トークン作成ロジックが SecurityTokenManager にある限り、セキュリティの脅威が軽減されます。
CloneCore メソッドをオーバーライドします。
public class MyClientCredentials : ClientCredentials { string creditCardNumber; public MyClientCredentials() { // Perform client credentials initialization. } protected MyClientCredentials(MyClientCredentials other) : base(other) { // Clone fields defined in this class. this.creditCardNumber = other.creditCardNumber; } public string CreditCardNumber { get { return this.creditCardNumber; } set { if (value == null) { throw new ArgumentNullException("value"); } this.creditCardNumber = value; } } public override SecurityTokenManager CreateSecurityTokenManager() { // Return your implementation of the SecurityTokenManager. return new MyClientCredentialsSecurityTokenManager(this); } protected override ClientCredentials CloneCore() { // Implement the cloning functionality. return new MyClientCredentials(this); } }
Public Class MyClientCredentials Inherits ClientCredentials Private creditCardNumberValue As String Public Sub New() End Sub ' Perform client credentials initialization. Protected Sub New(ByVal other As MyClientCredentials) MyBase.New(other) ' Clone fields defined in this class. Me.creditCardNumberValue = other.creditCardNumberValue End Sub Public Property CreditCardNumber() As String Get Return Me.creditCardNumberValue End Get Set If value Is Nothing Then Throw New ArgumentNullException("value") End If Me.creditCardNumberValue = value End Set End Property Public Overrides Function CreateSecurityTokenManager() As SecurityTokenManager ' Return your implementation of the SecurityTokenManager. Return New MyClientCredentialsSecurityTokenManager(Me) End Function Protected Overrides Function CloneCore() As ClientCredentials ' Implement the cloning functionality. Return New MyClientCredentials(Me) End Function End Class
カスタム クライアント セキュリティ トークン マネージャーを実装するには
ClientCredentialsSecurityTokenManager から派生する新しいクラスを定義します。
任意。 カスタム CreateSecurityTokenProvider(SecurityTokenRequirement) 実装を作成する必要がある場合は、SecurityTokenProvider メソッドをオーバーライドします。 カスタム セキュリティ トークン プロバイダーの詳細については、「方法: カスタム セキュリティ トークン プロバイダーを作成する」を参照してください。
任意。 カスタム CreateSecurityTokenAuthenticator(SecurityTokenRequirement, SecurityTokenResolver) 実装を作成する必要がある場合は、SecurityTokenAuthenticator メソッドをオーバーライドします。 カスタム セキュリティ トークン認証システムの詳細については、「方法: カスタム セキュリティ トークン認証システムを作成する」を参照してください。
任意。 カスタム CreateSecurityTokenSerializer を作成する必要がある場合は、SecurityTokenSerializer メソッドをオーバーライドします。 カスタム セキュリティ トークンおよびカスタム セキュリティ トークン シリアライザーの詳細については、「方法: カスタム トークンを作成する」を参照してください。
internal class MyClientCredentialsSecurityTokenManager : ClientCredentialsSecurityTokenManager { MyClientCredentials credentials; public MyClientCredentialsSecurityTokenManager(MyClientCredentials credentials) : base(credentials) { this.credentials = credentials; } public override SecurityTokenProvider CreateSecurityTokenProvider( SecurityTokenRequirement tokenRequirement) { // Return your implementation of the SecurityTokenProvider, if required. // This implementation delegates to the base class. return base.CreateSecurityTokenProvider(tokenRequirement); } public override SecurityTokenAuthenticator CreateSecurityTokenAuthenticator( SecurityTokenRequirement tokenRequirement, out SecurityTokenResolver outOfBandTokenResolver) { // Return your implementation of the SecurityTokenAuthenticator, if required. // This implementation delegates to the base class. return base.CreateSecurityTokenAuthenticator(tokenRequirement, out outOfBandTokenResolver); } public override SecurityTokenSerializer CreateSecurityTokenSerializer(SecurityTokenVersion version) { // Return your implementation of the SecurityTokenSerializer, if required. // This implementation delegates to the base class. return base.CreateSecurityTokenSerializer(version); } }
Friend Class MyClientCredentialsSecurityTokenManager Inherits ClientCredentialsSecurityTokenManager Private credentials As MyClientCredentials Public Sub New(ByVal credentials As MyClientCredentials) MyBase.New(credentials) Me.credentials = credentials End Sub Public Overrides Function CreateSecurityTokenProvider( _ ByVal tokenRequirement As SecurityTokenRequirement) As SecurityTokenProvider ' Return your implementation of the SecurityTokenProvider, if required. ' This implementation delegates to the base class. Return MyBase.CreateSecurityTokenProvider(tokenRequirement) End Function Public Overrides Function CreateSecurityTokenAuthenticator( _ ByVal tokenRequirement As SecurityTokenRequirement, _ ByRef outOfBandTokenResolver As SecurityTokenResolver) As SecurityTokenAuthenticator ' Return your implementation of the SecurityTokenAuthenticator, if required. ' This implementation delegates to the base class. Return MyBase.CreateSecurityTokenAuthenticator(tokenRequirement, outOfBandTokenResolver) End Function Public Overrides Function CreateSecurityTokenSerializer(ByVal version As SecurityTokenVersion) _ As SecurityTokenSerializer ' Return your implementation of the SecurityTokenSerializer, if required. ' This implementation delegates to the base class. Return MyBase.CreateSecurityTokenSerializer(version) End Function End Class
アプリケーション コードによるカスタム クライアント資格情報を使用するには
サービス インターフェイスを表す、生成されたクライアントのインスタンスを作成するか、または通信の対象となるサービスを指す ChannelFactory のインスタンスを作成します。
Behaviors コレクションから、システム指定のクライアント資格情報の動作を削除します。このコレクションには、Endpoint プロパティからアクセスできます。
カスタム資格情報クラスの新しいインスタンスを作成し、Behaviors コレクションに追加します。このコレクションには、Endpoint プロパティからアクセスできます。
// Create a client with the client endpoint configuration. CalculatorClient client = new CalculatorClient(); // Remove the ClientCredentials behavior. client.ChannelFactory.Endpoint.Behaviors.Remove<ClientCredentials>(); // Add a custom client credentials instance to the behaviors collection. client.ChannelFactory.Endpoint.Behaviors.Add(new MyClientCredentials());
' Create a client with the client endpoint configuration. Dim client As New CalculatorClient() ' Remove the ClientCredentials behavior. client.ChannelFactory.Endpoint.Behaviors.Remove(Of ClientCredentials)() ' Add a custom client credentials instance to the behaviors collection. client.ChannelFactory.Endpoint.Behaviors.Add(New MyClientCredentials())
上記の手順は、アプリケーション コードからクライアント資格情報を使用する方法を示しています。 WCF の資格情報は、アプリケーション構成ファイルを使用して構成することもできます。 ソースの変更、再コンパイル、再展開を行うことなくアプリケーションのパラメーターを変更できるため、ハードコーディングを行うよりもアプリケーション構成ファイルの使用を一般にお勧めします。
次の手順では、カスタム資格情報の構成をサポートする方法について説明します。
カスタム クライアント資格情報の構成ハンドラーの作成
ClientCredentialsElement から派生する新しいクラスを定義します。
任意。 アプリケーション構成を通じて公開する必要があるすべての追加構成パラメーターのプロパティを追加します。 次の例では、
CreditCardNumber
という名前のプロパティを追加します。BehaviorType プロパティをオーバーライドして、構成要素によって作成されたカスタム クライアント資格情報クラスの型を返します。
CreateBehavior メソッドをオーバーライドします。 このメソッドは、構成ファイルから読み込まれた設定に基づいてカスタム資格情報クラスのインスタンスを作成して返す役割を担います。 このメソッドから ApplyConfiguration(ClientCredentials) 基本メソッドを呼び出し、カスタム クライアント資格情報インスタンスに読み込まれたシステム指定の資格情報の設定を取得します。
任意。 手順 2. で追加のプロパティを追加している場合は、Properties プロパティをオーバーライドして、追加した構成設定が構成フレームワークから認識されるよう登録します。 追加したプロパティを基本クラスのプロパティと結合して、このカスタム クライアント資格情報の構成要素を通じてシステム指定の設定が構成されるようにします。
public class MyClientCredentialsConfigHandler : ClientCredentialsElement { ConfigurationPropertyCollection properties; public override Type BehaviorType { get { return typeof(MyClientCredentials); } } public string CreditCardNumber { get { return (string)base["creditCardNumber"]; } set { if (String.IsNullOrEmpty(value)) { value = String.Empty; } base["creditCardNumber"] = value; } } protected override ConfigurationPropertyCollection Properties { get { if (this.properties == null) { ConfigurationPropertyCollection properties = base.Properties; properties.Add(new ConfigurationProperty( "creditCardNumber", typeof(System.String), string.Empty, null, new StringValidator(0, 32, null), ConfigurationPropertyOptions.None)); this.properties = properties; } return this.properties; } } protected override object CreateBehavior() { MyClientCredentials creds = new MyClientCredentials(); creds.CreditCardNumber = CreditCardNumber; base.ApplyConfiguration(creds); return creds; } }
Public Class MyClientCredentialsConfigHandler Inherits ClientCredentialsElement Private propertiesValue As ConfigurationPropertyCollection Public Overrides ReadOnly Property BehaviorType() As Type Get Return GetType(MyClientCredentials) End Get End Property Public Property CreditCardNumber() As String Get Return CStr(MyBase.Item("creditCardNumber")) End Get Set If String.IsNullOrEmpty(value) Then value = String.Empty End If MyBase.Item("creditCardNumber") = value End Set End Property Protected Overrides ReadOnly Property Properties() As ConfigurationPropertyCollection Get If Me.propertiesValue Is Nothing Then Dim myProperties As ConfigurationPropertyCollection = MyBase.Properties myProperties.Add(New ConfigurationProperty( _ "creditCardNumber", _ GetType(System.String), _ String.Empty, _ Nothing, _ New StringValidator(0, 32, Nothing), _ ConfigurationPropertyOptions.None)) Me.propertiesValue = myProperties End If Return Me.propertiesValue End Get End Property Protected Overrides Function CreateBehavior() As Object Dim creds As New MyClientCredentials() creds.CreditCardNumber = Me.CreditCardNumber MyBase.ApplyConfiguration(creds) Return creds End Function End Class
構成ハンドラー クラスを作成したら、WCF の構成フレームワークに統合できます。 これにより、次の手順で示すように、カスタム クライアント資格情報をクライアント エンドポイント動作要素で使用できるようになります。
カスタム クライアント資格情報構成ハンドラーをアプリケーション構成に登録して使用するには
<extensions>
要素と<behaviorExtensions>
要素を構成ファイルに追加します。<add>
要素を<behaviorExtensions>
要素に追加し、name
属性に適切な値を設定します。type
属性を完全修飾型名に設定します。 また、アセンブリ名と他のアセンブリ属性を含めます。<system.serviceModel> <extensions> <behaviorExtensions> <add name="myClientCredentials" type="Microsoft.ServiceModel.Samples.MyClientCredentialsConfigHandler, CustomCredentials, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" /> </behaviorExtensions> </extensions> </system.serviceModel>
構成ハンドラーの登録後は、システム指定の
<clientCredentials>
要素の代わりに、同じ構成ファイル内でカスタム資格情報要素を使用できます。 システム指定のプロパティと、構成ハンドラーの実装に追加した任意の新規プロパティのどちらも使用できます。 次の例では、creditCardNumber
属性を使用して、カスタム プロパティの値を設定します。<behaviors> <endpointBehaviors> <behavior name="myClientCredentialsBehavior"> <myClientCredentials creditCardNumber="123-123-123"/> </behavior> </endpointBehaviors> </behaviors>
カスタム サービス資格情報を実装するには
ServiceCredentials から派生する新しいクラスを定義します。
任意。 追加している新しい資格情報の値に API を提供するために新しいプロパティを追加します。 新しい資格情報の値を追加しない場合は、この手順を省略します。 次の例では、
AdditionalCertificate
プロパティを追加します。CreateSecurityTokenManager メソッドをオーバーライドします。 カスタム クライアント資格情報が使用されると、WCF インフラストラクチャによって、このメソッドが自動的に呼び出されます。 このメソッドは、SecurityTokenManager クラスの実装のインスタンスを作成して返す役割を担います (次の手順で説明)。
任意。 CloneCore メソッドをオーバーライドします。 この手順は、カスタム クライアント資格情報の実装に新しいプロパティまたは内部フィールドを追加する場合にのみ必要になります。
public class MyServiceCredentials : ServiceCredentials { X509Certificate2 additionalCertificate; public MyServiceCredentials() { } protected MyServiceCredentials(MyServiceCredentials other) : base(other) { this.additionalCertificate = other.additionalCertificate; } public X509Certificate2 AdditionalCertificate { get { return this.additionalCertificate; } set { if (value == null) { throw new ArgumentNullException("value"); } this.additionalCertificate = value; } } public override SecurityTokenManager CreateSecurityTokenManager() { return base.CreateSecurityTokenManager(); } protected override ServiceCredentials CloneCore() { return new MyServiceCredentials(this); } }
Public Class MyServiceCredentials Inherits ServiceCredentials Private additionalCertificateValue As X509Certificate2 Public Sub New() End Sub Protected Sub New(ByVal other As MyServiceCredentials) MyBase.New(other) Me.additionalCertificate = other.additionalCertificate End Sub Public Property AdditionalCertificate() As X509Certificate2 Get Return Me.additionalCertificateValue End Get Set If value Is Nothing Then Throw New ArgumentNullException("value") End If Me.additionalCertificateValue = value End Set End Property Public Overrides Function CreateSecurityTokenManager() As SecurityTokenManager Return MyBase.CreateSecurityTokenManager() End Function Protected Overrides Function CloneCore() As ServiceCredentials Return New MyServiceCredentials(Me) End Function End Class
カスタム サービス セキュリティ トークン マネージャーを実装するには
ServiceCredentialsSecurityTokenManager クラスから派生する新しいクラスを定義します。
任意。 カスタム CreateSecurityTokenProvider 実装を作成する必要がある場合は、SecurityTokenProvider メソッドをオーバーライドします。 カスタム セキュリティ トークン プロバイダーの詳細については、「方法: カスタム セキュリティ トークン プロバイダーを作成する」を参照してください。
任意。 カスタム CreateSecurityTokenAuthenticator 実装を作成する必要がある場合は、SecurityTokenAuthenticator メソッドをオーバーライドします。 カスタム セキュリティ トークン認証システムの詳細については、「方法: カスタム セキュリティ トークン認証システムを作成する」のトピックを参照してください。
任意。 カスタム CreateSecurityTokenSerializer(SecurityTokenVersion) を作成する必要がある場合は、SecurityTokenSerializer メソッドをオーバーライドします。 カスタム セキュリティ トークンおよびカスタム セキュリティ トークン シリアライザーの詳細については、「方法: カスタム トークンを作成する」を参照してください。
internal class MyServiceCredentialsSecurityTokenManager : ServiceCredentialsSecurityTokenManager { MyServiceCredentials credentials; public MyServiceCredentialsSecurityTokenManager(MyServiceCredentials credentials) : base(credentials) { this.credentials = credentials; } public override SecurityTokenProvider CreateSecurityTokenProvider(SecurityTokenRequirement tokenRequirement) { // Return your implementation of SecurityTokenProvider, if required. // This implementation delegates to the base class. return base.CreateSecurityTokenProvider(tokenRequirement); } public override SecurityTokenAuthenticator CreateSecurityTokenAuthenticator(SecurityTokenRequirement tokenRequirement, out SecurityTokenResolver outOfBandTokenResolver) { // Return your implementation of SecurityTokenProvider, if required. // This implementation delegates to the base class. return base.CreateSecurityTokenAuthenticator(tokenRequirement, out outOfBandTokenResolver); } public override SecurityTokenSerializer CreateSecurityTokenSerializer(SecurityTokenVersion version) { // Return your implementation of SecurityTokenProvider, if required. // This implementation delegates to the base class. return base.CreateSecurityTokenSerializer(version); } }
Friend Class MyServiceCredentialsSecurityTokenManager Inherits ServiceCredentialsSecurityTokenManager Private credentials As MyServiceCredentials Public Sub New(ByVal credentials As MyServiceCredentials) MyBase.New(credentials) Me.credentials = credentials End Sub Public Overrides Function CreateSecurityTokenProvider(ByVal tokenRequirement As SecurityTokenRequirement) _ As SecurityTokenProvider ' Return your implementation of SecurityTokenProvider, if required. ' This implementation delegates to the base class. Return MyBase.CreateSecurityTokenProvider(tokenRequirement) End Function Public Overrides Function CreateSecurityTokenAuthenticator( _ ByVal tokenRequirement As SecurityTokenRequirement, _ ByRef outOfBandTokenResolver As SecurityTokenResolver) _ As SecurityTokenAuthenticator ' Return your implementation of SecurityTokenProvider, if required. ' This implementation delegates to the base class. Return MyBase.CreateSecurityTokenAuthenticator(tokenRequirement, outOfBandTokenResolver) End Function Public Overrides Function CreateSecurityTokenSerializer(ByVal version As SecurityTokenVersion) _ As SecurityTokenSerializer ' Return your implementation of SecurityTokenProvider, if required. ' This implementation delegates to the base class. Return MyBase.CreateSecurityTokenSerializer(version) End Function End Class
アプリケーション コードによるカスタム サービス資格情報を使用するには
ServiceHost のインスタンスを作成します。
Behaviors コレクションから、システム指定のサービス資格情報の動作を削除します。
カスタム サービス資格情報クラスの新しいインスタンスを作成し、これを Behaviors コレクションに追加します。
// Create a service host with a service type. ServiceHost serviceHost = new ServiceHost(typeof(Service)); // Remove the default ServiceCredentials behavior. serviceHost.Description.Behaviors.Remove<ServiceCredentials>(); // Add a custom service credentials instance to the collection. serviceHost.Description.Behaviors.Add(new MyServiceCredentials());
' Create a service host with a service type. Dim serviceHost As New ServiceHost(GetType(Service)) ' Remove the default ServiceCredentials behavior. serviceHost.Description.Behaviors.Remove(Of ServiceCredentials)() ' Add a custom service credentials instance to the collection. serviceHost.Description.Behaviors.Add(New MyServiceCredentials())
前の「To create a configuration handler for custom client credentials
」および「To register and use a custom client credentials configuration handler in the application configuration
」で説明した手順を使用して構成にサポートを追加します。構成ハンドラーの基本クラスとして、ClientCredentialsElement クラスではなく ServiceCredentialsElement クラスを使用する点のみが異なります。 カスタム サービス資格情報要素は、システム指定の <serviceCredentials>
要素を使用する場合にいつでも使用できます。