如何:创建自定义安全令牌提供程序
本主题介绍如何使用自定义安全令牌提供程序来创建新令牌类型,以及如何将该提供程序与自定义安全令牌管理器集成。
注意
如果在 System.IdentityModel.Tokens 命名空间中找到的系统提供的令牌不符合要求,请创建一个自定义令牌提供程序。
安全令牌提供程序会基于客户端或服务凭据中的信息创建一个安全令牌表示形式。 若要在 Windows Communication Foundation (WCF) 安全性中使用自定义安全令牌提供程序,需要创建自定义凭据和安全令牌管理器实现。
有关自定义凭据和安全令牌管理器的详细信息,请参阅演练:创建自定义客户端和服务凭据。
创建自定义安全令牌提供程序
定义一个从 SecurityTokenProvider 类派生的新类。
实现 GetTokenCore(TimeSpan) 方法。 该方法负责创建和返回安全令牌的实例。 下面的示例创建一个名为
MySecurityTokenProvider
的类,并重写 GetTokenCore(TimeSpan) 方法以返回 X509SecurityToken 类的实例。 该类构造函数需要 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
将自定义安全令牌提供程序与自定义安全令牌管理器集成
定义一个从 SecurityTokenManager 类派生的新类。 (下面的示例从 ClientCredentialsSecurityTokenManager 类派生,而该类又从 SecurityTokenManager 类派生。)
重写 CreateSecurityTokenProvider(SecurityTokenRequirement) 方法(如果尚未重写它)。
CreateSecurityTokenProvider(SecurityTokenRequirement) 方法负责返回 SecurityTokenProvider 类的一个实例,该实例与通过 WCF 安全框架传递给该方法的 SecurityTokenRequirement 参数相适。 修改此方法,以便在用相应的安全令牌参数调用它时,可以返回所实现的自定义安全令牌提供程序(在上一个过程中创建的)。 有关安全令牌管理器的详细信息,请参阅演练:创建自定义客户端和服务凭据。
向该方法中添加自定义逻辑,使其可以基于 SecurityTokenRequirement 参数返回自定义安全令牌提供程序。 下面的示例在满足令牌需求时返回自定义安全令牌提供程序。 这些要求包括一个 X.509 安全令牌以及消息方向(使用令牌进行消息输出)。 对于其他所有情况,该代码通过调用基类,针对其他安全令牌要求来维护系统提供的行为。
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
示例
下面演示了一个完整的 SecurityTokenProvider 实现,连同相应的 SecurityTokenManager 实现。
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