HOW TO:建立自訂安全性權杖驗證器
本主題會示範如何建立自訂安全性權杖驗證器,以及如何將其與自訂的安全性權杖管理員整合。安全性權杖驗證器會驗證傳入訊息所提供之安全性權杖的內容。如果驗證成功,驗證器便會傳回在進行評估時會傳回一組宣告之 IAuthorizationPolicy 執行個體的集合。
若要在 Windows Communication Foundation (WCF) 中使用自訂安全性權杖驗證器,您必須先建立自訂認證和安全性權杖管理員實作 (Implementation)。如需建立自訂認證和安全性權杖管理員的詳細資訊,請參閱 逐步解說:建立自訂用戶端與服務認證。如需認證、安全性權杖管理員,以及提供者和驗證器類別的詳細資訊,請參閱安全性架構。
程序
建立自訂安全性權杖驗證器
定義衍生自 SecurityTokenAuthenticator 類別的新類別。
覆寫 CanValidateTokenCore 方法。該方法會根據自訂驗證器是否能夠驗證傳入的權杖類型,傳回
true
或false
。覆寫 ValidateTokenCore 方法。這個方法需要適當地驗證權杖內容。如果權杖通過驗證步驟,此方法就會傳回 IAuthorizationPolicy 執行個體的集合。下列範例會使用將在下一個程序中建立的自訂授權原則實作。
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
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(); } }
上述程式碼會透過 CanValidateToken 方法傳回授權原則的集合。WCF 不會提供這個介面的公用實作。下列程序會示範如何根據您的需求來完成這項工作。
建立自訂授權原則
定義實作 IAuthorizationPolicy 介面的新類別。
實作 Id 唯讀屬性。使用類別建構函式 (Constructor) 來產生全域唯一識別項 (GUID),並在每次要求此屬性的值時將其傳回,就是實作此原則的一種方式
實作 Issuer 唯讀屬性。這個屬性需要傳回從權杖取得之宣告集的簽發者。這個簽發者應該會對應至權杖的簽發者,或是負責驗證該權杖內容的授權單位。下列範例會使用從上述程序所建立自訂安全性權杖驗證器傳遞到這個類別的簽發者宣告。自訂安全性權杖驗證器會使用系統提供的宣告集 (由 System 屬性傳回) 來表示使用者名稱權杖的簽發者。
實作 Evaluate 方法。這個方法會用以傳入安全性權杖內容為基礎的宣告,填入 (Populate) EvaluationContext 類別的執行個體 (當做引數傳入)。此方法會在完成評估時傳回
true
。當實作依賴對評估內容提供其他資訊之授權原則的存在,而需要的資訊尚未存在於評估內容時,這個方法便會傳回false
。在此情況下,如果這些授權原則中至少有一個修改了評估內容,WCF 將會在評估過針對傳入訊息所產生的所有其他授權原則之後,再度呼叫此方法。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
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; } }
逐步解說:建立自訂用戶端與服務認證會說明如何建立自訂認證和自訂安全性權杖管理員。為了使用在此建立的自訂安全性權杖驗證器,安全性權杖管理員的實作會經過修改,以便從 CreateSecurityTokenAuthenticator 方法傳回自訂驗證器。若有傳入適當的安全性權杖需求,此方法便會傳回驗證器。
將自訂安全性權杖驗證器與自訂安全性權杖管理員整合
覆寫自訂安全性權杖管理員實作中的 CreateSecurityTokenAuthenticator 方法。
將邏輯新增到方法中,讓方法能夠根據 SecurityTokenRequirement 參數傳回自訂安全性權杖驗證器。如果在權杖需求中權杖類型為使用者名稱 (由 UserName 屬性表示),而且安全性權杖驗證器被要求的訊息方向為輸入時 (由 Input 欄位表示),下列範例就會傳回自訂安全性權杖驗證器。
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
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; } }
另請參閱
工作
參考
SecurityTokenAuthenticator
SecurityTokenRequirement
SecurityTokenManager
UserNameSecurityToken