このトピックでは、カスタム セキュリティ トークン認証システムを作成する方法と、それをカスタム セキュリティ トークン マネージャーと統合する方法について説明します。 セキュリティ トークン認証子は、受信メッセージで提供されるセキュリティ トークンの内容を検証します。 検証が成功した場合、認証子は、評価時に一連の要求を返す IAuthorizationPolicy インスタンスのコレクションを返します。
Windows Communication Foundation (WCF) でカスタム セキュリティ トークン認証システムを使用するには、最初にカスタム資格情報とセキュリティ トークン マネージャーの実装を作成する必要があります。 カスタム資格情報とセキュリティ トークン マネージャーの作成の詳細については、「 チュートリアル: カスタム クライアントとサービス資格情報の作成」を参照してください。
プロシージャ
カスタム セキュリティ トークン認証システムを作成するには
SecurityTokenAuthenticator クラスから派生した新しいクラスを定義します。
CanValidateTokenCore メソッドをオーバーライドします。 このメソッドは、カスタム認証子が受信トークンの種類を検証できるかどうかに応じて、
trueまたはfalseを返します。ValidateTokenCore メソッドをオーバーライドします。 このメソッドは、トークンの内容を適切に検証する必要があります。 トークンが検証手順に合格すると、 IAuthorizationPolicy インスタンスのコレクションが返されます。 次の例では、次の手順で作成されるカスタム承認ポリシーの実装を使用します。
internal class MySecurityTokenAuthenticator : SecurityTokenAuthenticator { protected override bool CanValidateTokenCore(SecurityToken token) { // Check that the incoming token is a username token type that // can be validated by this implementation. return (token is UserNameSecurityToken); } protected override ReadOnlyCollection<IAuthorizationPolicy> ValidateTokenCore(SecurityToken token) { UserNameSecurityToken userNameToken = token as UserNameSecurityToken; // Validate the information contained in the username token. For demonstration // purposes, this code just checks that the user name matches the password. if (userNameToken.UserName != userNameToken.Password) { throw new SecurityTokenValidationException("Invalid user name or password"); } // Create just one Claim instance for the username token - the name of the user. DefaultClaimSet userNameClaimSet = new DefaultClaimSet( ClaimSet.System, new Claim(ClaimTypes.Name, userNameToken.UserName, Rights.PossessProperty)); List<IAuthorizationPolicy> policies = new List<IAuthorizationPolicy>(1); policies.Add(new MyAuthorizationPolicy(userNameClaimSet)); return policies.AsReadOnly(); } }Friend Class MySecurityTokenAuthenticator Inherits SecurityTokenAuthenticator Protected Overrides Function CanValidateTokenCore(ByVal token As SecurityToken) As Boolean ' Check that the incoming token is a username token type that ' can be validated by this implementation. Return (TypeOf token Is UserNameSecurityToken) End Function Protected Overrides Function ValidateTokenCore(ByVal token As SecurityToken) As ReadOnlyCollection(Of IAuthorizationPolicy) Dim userNameToken = TryCast(token, UserNameSecurityToken) ' Validate the information contained in the username token. For demonstration ' purposes, this code just checks that the user name matches the password. If userNameToken.UserName <> userNameToken.Password Then Throw New SecurityTokenValidationException("Invalid user name or password") End If ' Create just one Claim instance for the username token - the name of the user. Dim userNameClaimSet As New DefaultClaimSet(ClaimSet.System, _ New Claim(ClaimTypes.Name, _ userNameToken.UserName, _ Rights.PossessProperty)) Dim policies As New List(Of IAuthorizationPolicy)(1) policies.Add(New MyAuthorizationPolicy(userNameClaimSet)) Return policies.AsReadOnly() End Function End Class
前のコードは、 CanValidateToken(SecurityToken) メソッドの承認ポリシーのコレクションを返します。 WCF では、このインターフェイスのパブリック実装は提供されません。 次の手順では、独自の要件に合わせてこれを行う方法を示します。
カスタム承認ポリシーを作成するには
IAuthorizationPolicy インターフェイスを実装する新しいクラスを定義します。
Id読み取り専用プロパティを実装します。 このプロパティを実装する方法の 1 つは、クラス コンストラクターでグローバル一意識別子 (GUID) を生成し、このプロパティの値が要求されるたびにそれを返す方法です。
Issuer読み取り専用プロパティを実装します。 このプロパティは、トークンから得られた要求セットの発行元を返す必要があります。 この発行者は、トークンの発行者またはトークンの内容の検証を担当する機関に対応する必要があります。 次の例では、前の手順で作成したカスタム セキュリティ トークン認証子からこのクラスに渡された発行者要求を使用します。 カスタム セキュリティ トークン認証システムは、システム指定の要求セット ( System プロパティによって返されます) を使用して、ユーザー名トークンの発行者を表します。
Evaluate メソッドを実装します。 このメソッドは、(引数として渡される) EvaluationContext クラスのインスタンスに、受信セキュリティ トークンの内容に基づく要求を設定します。 このメソッドは、評価が完了したときに
trueを返します。 実装が評価コンテキストに追加情報を提供する他の承認ポリシーの存在に依存している場合、必要な情報がまだ評価コンテキストに存在しない場合、このメソッドはfalseを返すことができます。 その場合、WCF は、それらの承認ポリシーの少なくとも 1 つが評価コンテキストを変更した場合、受信メッセージに対して生成された他のすべての承認ポリシーを評価した後、メソッドを再度呼び出します。internal class MyAuthorizationPolicy : IAuthorizationPolicy { string id; ClaimSet tokenClaims; ClaimSet issuer; public MyAuthorizationPolicy(ClaimSet tokenClaims) { if (tokenClaims == null) { throw new ArgumentNullException("tokenClaims"); } this.issuer = tokenClaims.Issuer; this.tokenClaims = tokenClaims; this.id = Guid.NewGuid().ToString(); } public ClaimSet Issuer { get { return issuer; } } public string Id { get { return id; } } public bool Evaluate(EvaluationContext evaluationContext, ref object state) { // Add the token claim set to the evaluation context. evaluationContext.AddClaimSet(this, tokenClaims); // Return true if the policy evaluation is finished. return true; } }Friend Class MyAuthorizationPolicy Implements IAuthorizationPolicy Private _id As String Private _tokenClaims As ClaimSet Private _issuer As ClaimSet Public Sub New(ByVal tokenClaims As ClaimSet) If _tokenClaims Is Nothing Then Throw New ArgumentNullException("tokenClaims") End If Me._issuer = tokenClaims.Issuer Me._tokenClaims = tokenClaims Me._id = Guid.NewGuid().ToString() End Sub Public ReadOnly Property Issuer() As ClaimSet Implements IAuthorizationPolicy.Issuer Get Return _issuer End Get End Property Public ReadOnly Property Id() As String Implements System.IdentityModel.Policy.IAuthorizationComponent.Id Get Return _id End Get End Property Public Function Evaluate(ByVal evaluationContext As EvaluationContext, _ ByRef state As Object) As Boolean Implements IAuthorizationPolicy.Evaluate ' Add the token claim set to the evaluation context. evaluationContext.AddClaimSet(Me, _tokenClaims) ' Return true if the policy evaluation is finished. Return True End Function End Class
チュートリアル: カスタム クライアント資格情報とサービス資格情報の作成 では、カスタム資格情報とカスタム セキュリティ トークン マネージャーを作成する方法について説明します。 ここで作成したカスタム セキュリティ トークン認証システムを使用するために、セキュリティ トークン マネージャーの実装が変更され、 CreateSecurityTokenAuthenticator メソッドからカスタム認証子が返されます。 このメソッドは、適切なセキュリティ トークン要件が渡されたときに認証子を返します。
カスタム セキュリティ トークン認証システムをカスタム セキュリティ トークン マネージャーと統合するには
カスタム セキュリティ トークン マネージャーの実装で CreateSecurityTokenAuthenticator メソッドをオーバーライドします。
メソッドにロジックを追加して、 SecurityTokenRequirement パラメーターに基づいてカスタム セキュリティ トークン認証子を返せるようにします。 次の例では、トークン要件トークンの種類がユーザー名 ( UserName プロパティで表されます) で、セキュリティ トークン認証が要求されているメッセージの方向が入力 ( Input フィールドで表される) である場合、カスタム セキュリティ トークン認証子を返します。
internal class MyServiceCredentialsSecurityTokenManager : ServiceCredentialsSecurityTokenManager { ServiceCredentials credentials; public MyServiceCredentialsSecurityTokenManager(ServiceCredentials credentials) : base(credentials) { this.credentials = credentials; } public override SecurityTokenAuthenticator CreateSecurityTokenAuthenticator (SecurityTokenRequirement tokenRequirement, out SecurityTokenResolver outOfBandTokenResolver) { // Return your implementation of the SecurityTokenProvider based on the // tokenRequirement argument. SecurityTokenAuthenticator result; if (tokenRequirement.TokenType == SecurityTokenTypes.UserName) { MessageDirection direction = tokenRequirement.GetProperty<MessageDirection> (ServiceModelSecurityTokenRequirement.MessageDirectionProperty); if (direction == MessageDirection.Input) { outOfBandTokenResolver = null; result = new MySecurityTokenAuthenticator(); } else { result = base.CreateSecurityTokenAuthenticator(tokenRequirement, out outOfBandTokenResolver); } } else { result = base.CreateSecurityTokenAuthenticator(tokenRequirement, out outOfBandTokenResolver); } return result; } }Friend Class MyServiceCredentialsSecurityTokenManager Inherits ServiceCredentialsSecurityTokenManager Private credentials As ServiceCredentials Public Sub New(ByVal credentials As ServiceCredentials) MyBase.New(credentials) Me.credentials = credentials End Sub Public Overrides Function CreateSecurityTokenAuthenticator(ByVal tokenRequirement As SecurityTokenRequirement, _ <System.Runtime.InteropServices.Out()> _ ByRef outOfBandTokenResolver _ As SecurityTokenResolver) As SecurityTokenAuthenticator ' Return your implementation of the SecurityTokenProvider based on the ' tokenRequirement argument. Dim result As SecurityTokenAuthenticator If tokenRequirement.TokenType = SecurityTokenTypes.UserName Then Dim direction = tokenRequirement.GetProperty(Of MessageDirection)(ServiceModelSecurityTokenRequirement.MessageDirectionProperty) If direction = MessageDirection.Input Then outOfBandTokenResolver = Nothing result = New MySecurityTokenAuthenticator() Else result = MyBase.CreateSecurityTokenAuthenticator(tokenRequirement, _ outOfBandTokenResolver) End If Else result = MyBase.CreateSecurityTokenAuthenticator(tokenRequirement, _ outOfBandTokenResolver) End If Return result End Function End Class