Procedura: creare un provider di token di sicurezza personalizzati

In questo argomento viene illustrato come creare nuovi tipi di token con un provider di token di sicurezza personalizzati e come integrare il provider con un gestore di token di sicurezza personalizzati.

Nota

Creare un provider di token personalizzati se i token forniti dal sistema, presenti nello spazio dei nomi System.IdentityModel.Tokens, non corrispondono ai propri requisiti.

Il provider di token di sicurezza crea una rappresentazione dei token di sicurezza in base alle informazioni presenti nelle credenziali del client o del servizio. Per usare il provider di token di sicurezza personalizzato in Windows Communication Foundation (WCF), è necessario creare credenziali personalizzate e implementazioni del gestore del token di sicurezza.

Per altre informazioni sulle credenziali e sui gestori di token di sicurezza personalizzati, vedere Procedura dettagliata: Creazione di credenziali client e servizio personalizzate.

Per creare un provider di token di sicurezza personalizzati

  1. Definire una nuova classe derivata dalla classe SecurityTokenProvider.

  2. Implementa il metodo GetTokenCore(TimeSpan). Il metodo è responsabile della creazione e della restituzione di un'istanza del token di sicurezza. Nell'esempio seguente viene creata una classe denominata MySecurityTokenProvider ed eseguito l'override del metodo GetTokenCore(TimeSpan), per restituire un'istanza della classe X509SecurityToken. Il costruttore della classe richiede un'istanza della classe X509Certificate2.

    internal class MySecurityTokenProvider : SecurityTokenProvider
    {
        X509Certificate2 certificate;
    
        public MySecurityTokenProvider(X509Certificate2 certificate)
        {
            this.certificate = certificate;
        }
    
        protected override SecurityToken GetTokenCore(TimeSpan timeout)
        {
            return new X509SecurityToken(certificate);
        }
    }
    
    Friend Class MySecurityTokenProvider
        Inherits SecurityTokenProvider
        Private certificate As X509Certificate2
    
        Public Sub New(ByVal certificate As X509Certificate2)
            Me.certificate = certificate
    
        End Sub
    
        Protected Overrides Function GetTokenCore(ByVal timeout As TimeSpan) As SecurityToken
            Return New X509SecurityToken(certificate)
    
        End Function
    End Class
    

Per integrare un provider di token di sicurezza personalizzati con un gestore di token di sicurezza personalizzati

  1. Definire una nuova classe derivata dalla classe SecurityTokenManager. L'esempio seguente deriva dalla classe ClientCredentialsSecurityTokenManager, che deriva dalla classe SecurityTokenManager.

  2. Eseguire l'override del metodo CreateSecurityTokenProvider(SecurityTokenRequirement), se non lo si è già fatto.

    Il metodo CreateSecurityTokenProvider(SecurityTokenRequirement) è responsabile della restituzione di un'istanza della classe SecurityTokenProvider adatta al parametro SecurityTokenRequirement passato al metodo dal framework di sicurezza WCF. Modificare il metodo per restituire l'implementazione del provider di token di sicurezza personalizzati (creato nella procedura precedente), quando il metodo viene chiamato con un parametro del token di sicurezza appropriato. Per altre informazioni sui gestori di token di sicurezza, vedere Procedura dettagliata: Creazione di credenziali client e servizio personalizzate.

  3. Aggiungere logica personalizzata al metodo, per consentire la restituzione del provider di token di sicurezza personalizzati in base al parametro SecurityTokenRequirement. Nell'esempio seguente viene restituito il provider di token di sicurezza personalizzati, se i requisiti dei token vengono soddisfatti. I requisiti includono un token di sicurezza X.509 e la direzione dei messaggi (è necessario che il token venga usato per l'output dei messaggi). Per tutti gli altri casi, il codice chiama la classe di base per mantenere il comportamento fornito dal sistema per gli altri requisiti dei token di sicurezza.

internal class MyClientCredentialsSecurityTokenManager:ClientCredentialsSecurityTokenManager
{
    ClientCredentials credentials;

    public MyClientCredentialsSecurityTokenManager(ClientCredentials credentials)
        : base(credentials)
    {
        this.credentials = credentials;
    }

    public override SecurityTokenProvider CreateSecurityTokenProvider(
        SecurityTokenRequirement tokenRequirement)
    {
        // Return your implementation of the SecurityTokenProvider based on the
        // tokenRequirement argument.
        SecurityTokenProvider result;
        if (tokenRequirement.TokenType == SecurityTokenTypes.X509Certificate)
        {
            MessageDirection direction = tokenRequirement.GetProperty<MessageDirection>(
                ServiceModelSecurityTokenRequirement.MessageDirectionProperty);
            if (direction == MessageDirection.Output)
            {
                result = new MySecurityTokenProvider(credentials.ClientCertificate.Certificate);
            }
            else
            {
                result = base.CreateSecurityTokenProvider(tokenRequirement);
            }
        }
        else
        {
            result = base.CreateSecurityTokenProvider(tokenRequirement);
        }

        return result;
    }
}

Friend Class MyClientCredentialsSecurityTokenManager
    Inherits ClientCredentialsSecurityTokenManager
    Private credentials As ClientCredentials


    Public Sub New(ByVal credentials As ClientCredentials)
        MyBase.New(credentials)
        Me.credentials = credentials

    End Sub


    Public Overrides Function CreateSecurityTokenProvider(ByVal tokenRequirement As SecurityTokenRequirement) As SecurityTokenProvider
        ' Return your implementation of the SecurityTokenProvider based on the 
        ' tokenRequirement argument.
        Dim result As SecurityTokenProvider
        If tokenRequirement.TokenType = SecurityTokenTypes.X509Certificate Then
            Dim direction As MessageDirection = tokenRequirement.GetProperty(Of MessageDirection) _
               (ServiceModelSecurityTokenRequirement.MessageDirectionProperty)
            If direction = MessageDirection.Output Then
                result = New MySecurityTokenProvider(credentials.ClientCertificate.Certificate)
            Else
                result = MyBase.CreateSecurityTokenProvider(tokenRequirement)
            End If
        Else
            result = MyBase.CreateSecurityTokenProvider(tokenRequirement)
        End If

        Return result

    End Function
End Class

Esempio

Nell'esempio seguente viene illustrata un'implementazione completa di SecurityTokenProvider, insieme a un'implementazione di SecurityTokenManager corrispondente.

using System;
using System.IdentityModel.Selectors;
using System.IdentityModel.Tokens;
using System.Security.Cryptography.X509Certificates;
using System.ServiceModel;
using System.ServiceModel.Description;
using System.ServiceModel.Security.Tokens;

namespace CustomProvider
{
    internal class MySecurityTokenProvider : SecurityTokenProvider
    {
        X509Certificate2 certificate;

        public MySecurityTokenProvider(X509Certificate2 certificate)
        {
            this.certificate = certificate;
        }

        protected override SecurityToken GetTokenCore(TimeSpan timeout)
        {
            return new X509SecurityToken(certificate);
        }
    }

    internal class MyClientCredentialsSecurityTokenManager:ClientCredentialsSecurityTokenManager
    {
        ClientCredentials credentials;

        public MyClientCredentialsSecurityTokenManager(ClientCredentials credentials)
            : base(credentials)
        {
            this.credentials = credentials;
        }

        public override SecurityTokenProvider CreateSecurityTokenProvider(
            SecurityTokenRequirement tokenRequirement)
        {
            // Return your implementation of the SecurityTokenProvider based on the
            // tokenRequirement argument.
            SecurityTokenProvider result;
            if (tokenRequirement.TokenType == SecurityTokenTypes.X509Certificate)
            {
                MessageDirection direction = tokenRequirement.GetProperty<MessageDirection>(
                    ServiceModelSecurityTokenRequirement.MessageDirectionProperty);
                if (direction == MessageDirection.Output)
                {
                    result = new MySecurityTokenProvider(credentials.ClientCertificate.Certificate);
                }
                else
                {
                    result = base.CreateSecurityTokenProvider(tokenRequirement);
                }
            }
            else
            {
                result = base.CreateSecurityTokenProvider(tokenRequirement);
            }

            return result;
        }
    }
}
Imports System.IdentityModel.Selectors
Imports System.IdentityModel.Tokens
Imports System.Security.Permissions
Imports System.Security.Cryptography.X509Certificates
Imports System.ServiceModel
Imports System.ServiceModel.Description
Imports System.ServiceModel.Security.Tokens

Friend Class MySecurityTokenProvider
    Inherits SecurityTokenProvider
    Private certificate As X509Certificate2

    Public Sub New(ByVal certificate As X509Certificate2)
        Me.certificate = certificate

    End Sub

    Protected Overrides Function GetTokenCore(ByVal timeout As TimeSpan) As SecurityToken
        Return New X509SecurityToken(certificate)

    End Function
End Class

Friend Class MyClientCredentialsSecurityTokenManager
    Inherits ClientCredentialsSecurityTokenManager
    Private credentials As ClientCredentials


    Public Sub New(ByVal credentials As ClientCredentials)
        MyBase.New(credentials)
        Me.credentials = credentials

    End Sub


    Public Overrides Function CreateSecurityTokenProvider(ByVal tokenRequirement As SecurityTokenRequirement) As SecurityTokenProvider
        ' Return your implementation of the SecurityTokenProvider based on the 
        ' tokenRequirement argument.
        Dim result As SecurityTokenProvider
        If tokenRequirement.TokenType = SecurityTokenTypes.X509Certificate Then
            Dim direction As MessageDirection = tokenRequirement.GetProperty(Of MessageDirection) _
               (ServiceModelSecurityTokenRequirement.MessageDirectionProperty)
            If direction = MessageDirection.Output Then
                result = New MySecurityTokenProvider(credentials.ClientCertificate.Certificate)
            Else
                result = MyBase.CreateSecurityTokenProvider(tokenRequirement)
            End If
        Else
            result = MyBase.CreateSecurityTokenProvider(tokenRequirement)
        End If

        Return result

    End Function
End Class

Vedi anche