Cómo: Crear un autenticador de tokens de seguridad personalizado
En este tema se muestra cómo crear un autenticador de tokens de seguridad personalizado y cómo integrarlo con un administrador de tokens de seguridad personalizado. Un autenticador de tokens de seguridad valida el contenido de un token de seguridad proporcionado con un mensaje entrante. Si la validación es correcta, el autenticador devuelve una colección de instancias IAuthorizationPolicy que, cuando se evalúa, devuelve un conjunto de notificaciones.
Para utilizar un autenticador de tokens de seguridad personalizado en Windows Communication Foundation (WCF), debe crear primero credenciales personalizadas e implementaciones del administrador de tokens de seguridad. Para obtener más información sobre cómo crear credenciales personalizadas y un administrador de tokens de seguridad, vea Tutorial: Crear credenciales de cliente y servicio personalizadas. Para obtener más información sobre las credenciales, el administrador de tokens de seguridad y las clases de proveedor y de autenticador, vea Arquitectura de seguridad.
Procedimientos
Para crear un autenticador de token de seguridad personalizado
Defina una clase nueva derivada de la clase SecurityTokenAuthenticator.
Invalide el método CanValidateTokenCore. El método devuelve
true
ofalse
en función de si el autenticador personalizado puede validar el tipo de token entrante o no.Invalide el método ValidateTokenCore. Este método necesita validar adecuadamente el contenido del token. Si el token pasa la fase de la validación, devuelve una colección de instancias IAuthorizationPolicy. El ejemplo siguiente utiliza una implementación de la directiva de autorización personalizada que se creará en el procedimiento siguiente.
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(); } }
El código anterior devuelve una colección de directivas de autorización en el método CanValidateToken. WCF no proporciona ninguna implementación pública de esta interfaz. El procedimiento siguiente muestra cómo hacer esto para sus propios requisitos.
Para crear una directiva de autorización personalizada
Defina una nueva clase que implementa la interfaz IAuthorizationPolicy.
Implemente la propiedad de solo lectura Id. Una manera de implementar esta propiedad es generar un identificador único global (GUID) en el constructor de clase y devolverlo cada vez que se solicita el valor para esta propiedad.
Implemente la propiedad de solo lectura Issuer. Esta propiedad necesita devolver un emisor de los conjuntos de notificaciones que se obtienen del token. Este emisor debería corresponderse con el emisor del token o con una autoridad que sea responsable de validar el contenido del token. El ejemplo siguiente utiliza la notificación del emisor que se pasó a esta clase desde el autenticador de tokens de seguridad personalizado creado en el procedimiento anterior. El autenticador de tokens de seguridad personalizado utiliza el conjunto de notificaciones proporcionado por el sistema (devuelto por la propiedad System) para representar el emisor del token del nombre de usuario.
Implemente el método Evaluate. Este método rellena una instancia de la clase EvaluationContext (pasadas como argumento) con notificaciones basadas en el contenido del token de seguridad entrante. El método devuelve
true
cuando se hace con la evaluación. En los casos en los que la implementación confía en la presencia de otras directivas de autorización que proporcionan información adicional al contexto de la evaluación, este método puede devolverfalse
si la información necesaria no se encuentra todavía en el contexto de la evaluación. En ese caso, WCF llamará de nuevo al método después de evaluar el resto de las directivas de autorización generadas para el mensaje entrante si, por lo menos, una de esas directivas de autorización modificó el contexto de evaluación.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; } }
Tutorial: Crear credenciales de cliente y servicio personalizadas describe cómo crear credenciales personalizadas y un administrador de tokens de seguridad personalizado. Para utilizar el autenticador de tokens de seguridad personalizado creado aquí, se modificará una implementación del administrador de tokens de seguridad para devolver el autenticador personalizado desde el método CreateSecurityTokenAuthenticator. El método devuelve un autenticador cuando se pasa un requisito de token de seguridad adecuado.
Para integrar un autenticador de tokens de seguridad personalizado con un administrador de tokens de seguridad personalizado
Invalide el método CreateSecurityTokenAuthenticator en la implementación del administrador de tokens de seguridad personalizada.
Agregue la lógica al método para habilitarlo con objeto de devolver su autenticador de tokens de seguridad personalizado basado en el parámetro SecurityTokenRequirement. El ejemplo siguiente devuelve un autenticador de tokens de seguridad personalizado si el tipo de token de requisitos de token es un nombre de usuario (representado por la propiedad UserName) y la dirección del mensaje para la que se solicita el autenticador de tokens de seguridad es la entrada (representada por el campo 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; } }
Vea también
Tareas
Cómo crear un proveedor de tokens de seguridad personalizado
Referencia
SecurityTokenAuthenticator
SecurityTokenRequirement
SecurityTokenManager
UserNameSecurityToken
Conceptos
Tutorial: Crear credenciales de cliente y servicio personalizadas
Arquitectura de seguridad