Instrukcja: tworzenie niestandardowego uwierzytelniacza tokenu zabezpieczeń

W tym temacie przedstawiono sposób tworzenia niestandardowego uwierzytelniającego tokenów zabezpieczających oraz jego integracji z niestandardowym menedżerem tokenów zabezpieczających. Uwierzytelniacz tokenu zabezpieczającego weryfikuje zawartość tokenu zabezpieczającego dostarczonego z komunikatem przychodzącym. Jeśli walidacja zakończy się pomyślnie, uwierzytelniacz zwróci kolekcję IAuthorizationPolicy wystąpień, które po ich ocenie zwracają zestaw oświadczeń.

Aby użyć niestandardowego uwierzytelniania tokenu zabezpieczeń w programie Windows Communication Foundation (WCF), należy najpierw utworzyć niestandardowe poświadczenia i implementacje menedżera tokenów zabezpieczeń. Aby uzyskać więcej informacji na temat tworzenia poświadczeń niestandardowych i menedżera tokenów zabezpieczających, zobacz Przewodnik: tworzenie niestandardowych poświadczeń klienta i usługi.

Procedures

Aby utworzyć niestandardowy mechanizm uwierzytelniania tokenu zabezpieczającego

  1. Zdefiniuj nową klasę pochodzącą z klasy SecurityTokenAuthenticator.

  2. Zastąp metodę CanValidateTokenCore. Metoda zwraca true lub false w zależności od tego, czy niestandardowy wystawca uwierzytelniający może zweryfikować typ tokenu przychodzącego, czy nie.

  3. Zastąp metodę ValidateTokenCore. Ta metoda musi odpowiednio zweryfikować zawartość tokenu. Jeśli token przejdzie krok weryfikacji, zwraca kolekcję IAuthorizationPolicy wystąpień. W poniższym przykładzie użyto niestandardowej implementacji zasad autoryzacji, która zostanie utworzona w następnej procedurze.

    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
    

Poprzedni kod zwraca kolekcję zasad autoryzacji w metodzie CanValidateToken(SecurityToken) . Program WCF nie zapewnia publicznej implementacji tego interfejsu. Poniższa procedura pokazuje, jak to zrobić dla własnych wymagań.

Aby utworzyć niestandardowe zasady autoryzacji

  1. Zdefiniuj nową klasę implementowania interfejsu IAuthorizationPolicy .

  2. Zaimplementuj Id właściwość tylko do odczytu. Jednym ze sposobów zaimplementowania tej właściwości jest wygenerowanie globalnie unikatowego identyfikatora (GUID) w konstruktorze klasy i zwrócenie jej za każdym razem, gdy żądana jest wartość tej właściwości.

  3. Zaimplementuj Issuer właściwość tylko do odczytu. Ta właściwość musi zwrócić wystawcę zestawów oświadczeń uzyskanych z tokenu. Ten wystawca powinien odpowiadać wystawcy tokenu lub urzędu odpowiedzialnego za weryfikowanie zawartości tokenu. W poniższym przykładzie użyto oświadczenia wystawcy przekazanego do tej klasy z niestandardowego wystawcy uwierzytelniającego tokenu zabezpieczającego utworzonego w poprzedniej procedurze. Niestandardowy uwierzytelniacz tokenu zabezpieczającego wykorzystuje dostarczony przez system zestaw oświadczeń (zwracany przez System właściwość) do reprezentowania wystawcy tokenu nazwy użytkownika.

  4. Zaimplementuj metodę Evaluate . Ta metoda wypełnia wystąpienie EvaluationContext klasy (przekazane jako argument) oświadczeniami opartymi na przychodzącej zawartości tokenu zabezpieczającego. Metoda zwraca true po zakończeniu ewaluacji. W przypadkach, gdy implementacja opiera się na obecności innych zasad autoryzacji, które dostarczają dodatkowych informacji do kontekstu oceny, ta metoda może zwrócić false , jeśli wymagane informacje nie są jeszcze obecne w kontekście oceny. W takim przypadku program WCF ponownie wywoła metodę po ocenie wszystkich innych zasad autoryzacji wygenerowanych dla komunikatu przychodzącego, jeśli co najmniej jedna z tych zasad autoryzacji zmodyfikowała kontekst oceny.

    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
    

Przewodnik: Tworzenie niestandardowych poświadczeń klienta i usługi opisuje sposób tworzenia poświadczeń niestandardowych i niestandardowego menedżera tokenów zabezpieczających. Aby użyć niestandardowego uwierzytelniacza tokenu zabezpieczającego utworzonego tutaj, implementacja menedżera tokenów zabezpieczających jest modyfikowana w celu zwrócenia niestandardowego uwierzytelniacza z metody CreateSecurityTokenAuthenticator. Metoda zwraca uwierzytelniacz, gdy zostanie spełnione odpowiednie wymaganie dotyczące tokenu zabezpieczającego.

Aby zintegrować niestandardowy uwierzytelniacz tokenów zabezpieczających z niestandardowym menedżerem tokenów zabezpieczających

  1. Zastąp metodę CreateSecurityTokenAuthenticator w swojej niestandardowej implementacji menedżera tokenów zabezpieczających.

  2. Dodaj logikę do metody, aby umożliwić jej zwrócenie niestandardowego autentykatora tokenu zabezpieczeń na podstawie parametru SecurityTokenRequirement. Poniższy przykład zwraca niestandardowy uwierzytelniający tokenu zabezpieczającego, jeśli typ wymaganego tokenu to nazwa użytkownika (reprezentowana przez właściwość UserName), a kierunek komunikatu, dla którego żądany jest uwierzytelniający tokenu zabezpieczającego, jest skierowany do wejścia (reprezentowany przez pole 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
    

Zobacz także