Практическое руководство. Создание пользовательского поставщика маркеров безопасности
В этом разделе показано, как создавать новые типы маркеров с помощью поставщика пользовательских маркеров безопасности и как интегрировать поставщик с диспетчером пользовательских маркеров безопасности.
Примечание.
Поставщик пользовательских маркеров следует создавать, если предоставляемые системой маркеры в пространстве имен 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 параметру, SecurityTokenRequirement переданного методу платформой безопасности WCF. Измените метод, чтобы он возвращал реализацию поставщика пользовательских маркеров безопасности (созданную перед этим), когда этот метод вызывается с соответствующим параметром маркера безопасности. Дополнительные сведения о диспетчере маркеров безопасности см. в пошаговом руководстве по созданию пользовательских учетных данных клиента и службы.
Добавьте в метод соответствующие инструкции, чтобы он мог возвращать поставщик пользовательских маркеров безопасности на основании параметра 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