如何:创建自定义安全令牌提供程序

本主题介绍如何使用自定义安全令牌提供程序来创建新令牌类型,以及如何将该提供程序与自定义安全令牌管理器集成。

ms734703.note(zh-cn,VS.100).gif注意:
如果在 System.IdentityModel.Tokens 命名空间中找到的系统提供的令牌不符合要求,请创建一个自定义令牌提供程序。

安全令牌提供程序会基于客户端或服务凭据中的信息创建一个安全令牌表示形式。若要在 Windows Communication Foundation (WCF) 安全中使用自定义安全令牌提供程序,则必须创建自定义凭据和安全令牌管理器实现。

有关自定义凭据和安全令牌管理器的更多信息,请参见演练:创建自定义客户端和服务凭据

有关凭据、安全令牌管理器、提供程序和身份验证器类的更多信息,请参见安全体系结构

创建自定义安全令牌提供程序

  1. 定义一个从 SecurityTokenProvider 类派生的新类。

  2. 实现 GetTokenCore 方法。该方法负责创建和返回安全令牌的实例。下面的示例创建一个名为 MySecurityTokenProvider 的类,并重写 GetTokenCore 方法以返回 X509SecurityToken 类的实例。该类构造函数需要 X509Certificate2 类的一个实例。

    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 
    
    internal class MySecurityTokenProvider : SecurityTokenProvider
    {
        X509Certificate2 certificate;
    
        public MySecurityTokenProvider(X509Certificate2 certificate)
        {
            this.certificate = certificate;
        }
    
        protected override SecurityToken GetTokenCore(TimeSpan timeout)
        {
            return new X509SecurityToken(certificate);
        }
    }
    

将自定义安全令牌提供程序与自定义安全令牌管理器集成

  1. 定义一个从 SecurityTokenManager 类派生的新类。(下面的示例从 ClientCredentialsSecurityTokenManager 类派生,而该类又从 SecurityTokenManager 类派生。)

  2. 重写 CreateSecurityTokenProvider 方法(如果尚未重写它)。

    CreateSecurityTokenProvider 方法负责返回 SecurityTokenProvider 类的一个实例,该实例与通过 WCF 安全框架传递给该方法的 SecurityTokenRequirement 参数相对应。修改此方法,以便在用相应的安全令牌参数调用它时,可以返回所实现的自定义安全令牌提供程序(在上一个过程中创建的)。有关安全令牌管理器的更多信息,请参见演练:创建自定义客户端和服务凭据

  3. 向该方法中添加自定义逻辑,使其可以基于 SecurityTokenRequirement 参数返回自定义安全令牌提供程序。下面的示例在满足令牌要求时返回自定义安全令牌提供程序。这些要求包括一个 X.509 安全令牌以及消息方向(使用令牌进行消息输出)。对于其他所有情况,该代码通过调用基类,针对其他安全令牌要求来维护系统提供的行为。

Friend Class MyClientCredentialsSecurityTokenManager
    Inherits ClientCredentialsSecurityTokenManager
    Private credentials As ClientCredentials
    
    
    Public Sub New(ByVal credentials As ClientCredentials) 
        MyBase.New(credentials)
        Me.credentials = credentials
    
    End Sub 'New
    
    
    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 
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;
    }
}

示例

下面演示了一个完整的 SecurityTokenProvider 实现,连同相应的 SecurityTokenManager 实现。

Imports System
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

<assembly: SecurityPermission(SecurityAction.RequestMinimum, Execution := True)>
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 'New
    
    
    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 
using System;
using System.IdentityModel.Selectors;
using System.IdentityModel.Tokens;
using System.Security.Permissions;
using System.Security.Cryptography.X509Certificates;
using System.ServiceModel;
using System.ServiceModel.Description;
using System.ServiceModel.Security.Tokens;

[assembly: SecurityPermission(SecurityAction.RequestMinimum, Execution = true)]
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;
        }
    }
}

另请参见

参考

SecurityTokenProvider
SecurityTokenRequirement
SecurityTokenManager
X509SecurityToken

概念

演练:创建自定义客户端和服务凭据
如何:创建自定义安全令牌身份验证器
安全体系结构