Événements
Créer des applications intelligentes
17 mars, 21 h - 21 mars, 10 h
Rejoignez la série de rencontres pour créer des solutions IA évolutives basées sur des cas d’usage réels avec d’autres développeurs et experts.
S’inscrire maintenantCe navigateur n’est plus pris en charge.
Effectuez une mise à niveau vers Microsoft Edge pour tirer parti des dernières fonctionnalités, des mises à jour de sécurité et du support technique.
Cette rubrique contient des instructions permettant de créer un jeton de sécurité personnalisé à l'aide de la classe SecurityToken et de l'intégrer à un fournisseur et authentificateur de jetons de sécurité personnalisés. Pour obtenir un exemple de code complet, consultez l’exemple Jeton personnalisé.
Un jeton de sécurité est essentiellement un élément XML utilisé par le framework de sécurité Windows Communication Foundation (WCF) pour représenter des revendications à propos d’un expéditeur dans du message SOAP. La sécurité WCF fournit plusieurs jetons pour les modes d’authentification fournis par le système. Les exemples comprennent un jeton de sécurité de certificat X.509 représenté par la classe X509SecurityToken ou un jeton de sécurité de nom d'utilisateur représenté par la classe UserNameSecurityToken.
Il peut arriver qu'un mode d'authentification ou que des informations d'identification ne soient pas prises en charge par les types fournis. Dans un tel cas, il est nécessaire de créer un jeton de sécurité personnalisé permettant de fournir une représentation XML des informations d'identification personnalisées dans les messages SOAP.
Les procédures suivantes montrent comment créer un jeton de sécurité personnalisé et l’intégrer à une infrastructure de sécurité WCF. Cette rubrique contient des instructions permettant de créer un jeton de carte de crédit utilisé pour passer des informations relatives à la carte de crédit du client au serveur.
Pour plus d’informations sur les informations d’identification personnalisées et le gestionnaire de jetons de sécurité, consultez la Procédure pas à pas : Création d’informations d’identification de client et de service personnalisées.
Consultez l'espace de noms System.IdentityModel.Tokens pour obtenir davantage de classes représentant des jetons de sécurité.
Une application cliente doit être créée de manière à permettre la spécification d'informations de carte de crédit pour l'infrastructure de sécurité. Une classe d'informations d'identification client personnalisées permet à l'application d'accéder à ces informations. La première étape consiste à créer une classe qui représente les informations de carte de crédit au sein des informations d'identification client personnalisées.
Définissez une nouvelle classe qui représente les informations de carte de crédit pour l'application. L'exemple suivant nomme la classe CreditCardInfo
.
Ajoutez les propriétés adéquates à cette classe pour permettre à une application de définir les informations requises pour le jeton personnalisé. Dans notre exemple, cette classe dispose de trois propriétés : CardNumber
, CardIssuer
et ExpirationDate
.
public class CreditCardInfo
{
string cardNumber;
string cardIssuer;
DateTime expirationDate;
public CreditCardInfo(string cardNumber, string cardIssuer, DateTime expirationDate)
{
this.cardNumber = cardNumber;
this.cardIssuer = cardIssuer;
this.expirationDate = expirationDate;
}
public string CardNumber
{
get { return this.cardNumber; }
}
public string CardIssuer
{
get { return this.cardIssuer; }
}
public DateTime ExpirationDate
{
get { return this.expirationDate; }
}
}
Public Class CreditCardInfo
Private _cardNumber As String
Private _cardIssuer As String
Private _expirationDate As DateTime
Public Sub New(ByVal cardNumber As String, ByVal cardIssuer As String, _
ByVal expirationDate As DateTime)
Me._cardNumber = cardNumber
Me._cardIssuer = cardIssuer
Me._expirationDate = expirationDate
End Sub
Public ReadOnly Property CardNumber() As String
Get
Return Me._cardNumber
End Get
End Property
Public ReadOnly Property CardIssuer() As String
Get
Return Me._cardIssuer
End Get
End Property
Public ReadOnly Property ExpirationDate() As DateTime
Get
Return Me._expirationDate
End Get
End Property
End Class
Vous devez ensuite créer une classe qui représente le jeton de sécurité personnalisé. Cette classe est utilisée par les classes de fournisseur de jetons de sécurité, d’authentificateur et de sérialiseur pour transmettre les informations relatives au jeton de sécurité à vers et à partir de l’infrastructure de sécurité WCF.
Définissez une nouvelle classe dérivée de la classe SecurityToken. Cet exemple crée une classe nommée CreditCardToken
.
Remplacez la propriété Id. Cette propriété est utilisée pour obtenir l'identificateur local du jeton de sécurité qui permet de renvoyer à la représentation XML de ce dernier à partir des autres éléments figurant dans les messages SOAP. Dans cet exemple, l'identificateur de jeton peut être passé à cette propriété comme paramètre de constructeur ou un nouvel identificateur aléatoire est généré à chaque fois qu'une instance de jeton de sécurité est créée.
Implémentez la propriété SecurityKeys. Cette propriété retourne une collection de clés de sécurité représentée par l'instance de jeton de sécurité. Ces clés peuvent être utilisées par WCF pour signer ou chiffrer les parties des messages SOAP. Dans cet exemple, le jeton de sécurité de carte de crédit ne peut pas contenir n'importe quelle clé de sécurité, c'est pourquoi l'implémentation retourne toujours une collection vide.
Remplacez les propriétés ValidFrom et ValidTo. Ces propriétés sont utilisées par WCF afin de déterminer si l’instance de jeton de sécurité est valide. Dans cet exemple, seule une date d'expiration est définie pour le jeton de carte de crédit, par conséquent la propriété ValidFrom
retourne la valeur DateTime, laquelle représente l'heure et la date de création de l'instance.
class CreditCardToken : SecurityToken
{
CreditCardInfo cardInfo;
DateTime effectiveTime = DateTime.UtcNow;
string id;
ReadOnlyCollection<SecurityKey> securityKeys;
public CreditCardToken(CreditCardInfo cardInfo) : this(cardInfo, Guid.NewGuid().ToString()) { }
public CreditCardToken(CreditCardInfo cardInfo, string id)
{
if (cardInfo == null)
{
throw new ArgumentNullException("cardInfo");
}
if (id == null)
{
throw new ArgumentNullException("id");
}
this.cardInfo = cardInfo;
this.id = id;
// The credit card token is not capable of any cryptography.
this.securityKeys = new ReadOnlyCollection<SecurityKey>(new List<SecurityKey>());
}
public CreditCardInfo CardInfo
{
get { return this.cardInfo; }
}
public override ReadOnlyCollection<SecurityKey> SecurityKeys
{
get { return this.securityKeys; }
}
public override DateTime ValidFrom
{
get { return this.effectiveTime; }
}
public override DateTime ValidTo
{
get { return this.cardInfo.ExpirationDate; }
}
public override string Id
{
get { return this.id; }
}
}
Friend Class CreditCardToken
Inherits SecurityToken
Private _cardInfo As CreditCardInfo
Private _effectiveTime As DateTime = DateTime.UtcNow
Private _id As String
Private _securityKeys As ReadOnlyCollection(Of SecurityKey)
Public Sub New(ByVal cardInfo As CreditCardInfo)
Me.New(cardInfo, Guid.NewGuid().ToString())
End Sub
Public Sub New(ByVal cardInfo As CreditCardInfo, _
ByVal id As String)
If cardInfo Is Nothing Then
Throw New ArgumentNullException("cardInfo")
End If
If id Is Nothing Then
Throw New ArgumentNullException("id")
End If
Me._cardInfo = cardInfo
Me._id = id
' The credit card token is not capable of any cryptography.
Me._securityKeys = New ReadOnlyCollection(Of SecurityKey)(New List(Of SecurityKey)())
End Sub
Public ReadOnly Property CardInfo() As CreditCardInfo
Get
Return Me._cardInfo
End Get
End Property
Public Overrides ReadOnly Property SecurityKeys() As ReadOnlyCollection(Of SecurityKey)
Get
Return Me._securityKeys
End Get
End Property
Public Overrides ReadOnly Property ValidFrom() As DateTime
Get
Return Me._effectiveTime
End Get
End Property
Public Overrides ReadOnly Property ValidTo() As DateTime
Get
Return Me._cardInfo.ExpirationDate
End Get
End Property
Public Overrides ReadOnly Property Id() As String
Get
Return Me._id
End Get
End Property
End Class
Lorsqu'un nouveau jeton de sécurité est créé, la classe SecurityTokenParameters doit à nouveau être implémentée. L’implémentation est utilisée dans la configuration de l’élément de liaison de sécurité afin de représenter un nouveau type de jeton. La classe des paramètres de jeton de sécurité sert de modèle, lequel permet de mettre en correspondance la véritable instance de jeton de sécurité lorsqu'un message est traité. Ce modèle contient des propriétés supplémentaires qu'une application peut utiliser afin de spécifier les critères que le jeton de sécurité doit respecter pour pouvoir être utilisé ou authentifié. L’exemple suivant n’ajoute pas de propriétés supplémentaires ; par conséquent, seul le type de jeton de sécurité est mis en correspondance lorsque l’infrastructure WCF recherche une instance de jeton de sécurité à utiliser ou à valider.
Définissez une nouvelle classe dérivée de la classe SecurityTokenParameters.
Implémentez la méthode CloneCore. Copiez tous les champs internes définis dans votre classe, le cas échéant. Cet exemple ne définit aucun champ supplémentaire.
Implémentez la propriété en lecture seule SupportsClientAuthentication. Cette propriété retourne true
si le type de jeton de sécurité représenté par cette classe peut être utilisé pour authentifier un client auprès d'un service. Dans cet exemple, le jeton de sécurité de carte de crédit peut être utilisé pour authentifier un client auprès d'un service.
Implémentez la propriété en lecture seule SupportsServerAuthentication. Cette propriété retourne true
si le type de jeton de sécurité représenté par cette classe peut être utilisé pour authentifier un service auprès d'un client. Dans cet exemple, le jeton de sécurité de carte de crédit ne peut pas être utilisé pour authentifier un service auprès d'un client.
Implémentez la propriété en lecture seule SupportsClientWindowsIdentity. Cette propriété retourne true
si le type de jeton de sécurité représenté par cette classe peut être mappé à un compte Windows. Si c'est le cas, le résultat de l'authentification est représenté par une instance de la classe WindowsIdentity. Dans cet exemple, le jeton ne peut pas être mappé à un compte Windows.
Implémentez la méthode CreateKeyIdentifierClause(SecurityToken, SecurityTokenReferenceStyle). Cette méthode est appelée par le framework de sécurité WCF lorsque ce dernier requiert une référence à une instance de jeton de sécurité représentée par cette classe de paramètres de jeton de sécurité. La véritable instance de jeton de sécurité et le type SecurityTokenReferenceStyle qui spécifie le type de la référence demandée sont tous les deux passés à cette méthode sous forme d’arguments. Dans cet exemple, seules les références internes sont prises en charge par le jeton de sécurité de carte de crédit. La classe SecurityToken dispose d'une fonctionnalité permettant de créer des références internes ; l'implémentation ne nécessite donc pas de code supplémentaire.
Implémentez la méthode InitializeSecurityTokenRequirement(SecurityTokenRequirement). Cette méthode est appelée par WCF pour convertir l’instance de classe de paramètres de jeton de sécurité en instance de la classe SecurityTokenRequirement. Le résultat est utilisé par les fournisseurs de jeton de sécurité pour créer l'instance de jeton de sécurité adéquate.
public class CreditCardTokenParameters : SecurityTokenParameters
{
public CreditCardTokenParameters()
{
}
protected CreditCardTokenParameters(CreditCardTokenParameters other)
: base(other)
{
}
protected override SecurityTokenParameters CloneCore()
{
return new CreditCardTokenParameters(this);
}
protected override void InitializeSecurityTokenRequirement(SecurityTokenRequirement requirement)
{
requirement.TokenType = Constants.CreditCardTokenType;
return;
}
// A credit card token has no cryptography, no windows identity, and supports only client authentication.
protected override bool HasAsymmetricKey
{
get { return false; }
}
protected override bool SupportsClientAuthentication
{
get { return true; }
}
protected override bool SupportsClientWindowsIdentity
{
get { return false; }
}
protected override bool SupportsServerAuthentication
{
get { return false; }
}
protected override SecurityKeyIdentifierClause CreateKeyIdentifierClause(SecurityToken token, SecurityTokenReferenceStyle referenceStyle)
{
if (referenceStyle == SecurityTokenReferenceStyle.Internal)
{
return token.CreateKeyIdentifierClause<LocalIdKeyIdentifierClause>();
}
else
{
throw new NotSupportedException("External references are not supported for credit card tokens");
}
}
}
Public Class CreditCardTokenParameters
Inherits SecurityTokenParameters
Public Sub New()
End Sub
Protected Sub New(ByVal other As CreditCardTokenParameters)
MyBase.New(other)
End Sub
Protected Overrides Function CloneCore() As SecurityTokenParameters
Return New CreditCardTokenParameters(Me)
End Function
Protected Overrides Sub InitializeSecurityTokenRequirement(ByVal requirement As SecurityTokenRequirement)
requirement.TokenType = Constants.CreditCardTokenType
Return
End Sub
' A credit card token has no cryptography, no windows identity, and supports only client authentication.
Protected Overrides ReadOnly Property HasAsymmetricKey() As Boolean
Get
Return False
End Get
End Property
Protected Overrides ReadOnly Property SupportsClientAuthentication() As Boolean
Get
Return True
End Get
End Property
Protected Overrides ReadOnly Property SupportsClientWindowsIdentity() As Boolean
Get
Return False
End Get
End Property
Protected Overrides ReadOnly Property SupportsServerAuthentication() As Boolean
Get
Return False
End Get
End Property
Protected Overrides Function CreateKeyIdentifierClause(ByVal token As SecurityToken, _
ByVal referenceStyle As SecurityTokenReferenceStyle) As SecurityKeyIdentifierClause
If referenceStyle = SecurityTokenReferenceStyle.Internal Then
Return token.CreateKeyIdentifierClause(Of LocalIdKeyIdentifierClause)()
Else
Throw New NotSupportedException("External references are not supported for credit card tokens")
End If
End Function
End Class
Les jetons de sécurité sont transmis dans les messages SOAP. Cette opération nécessite un mécanisme de traduction entre la représentation de jeton de sécurité en mémoire et la représentation en transmission. WCF utilise un sérialiseur de jeton de sécurité pour accomplir cette tâche. Chaque jeton personnalisé doit être accompagné par un sérialiseur de jeton de sécurité personnalisé pouvant le sérialiser et le désérialiser à partir des messages SOAP.
Notes
Les clés dérivées sont activées par défaut. Si vous créez un jeton de sécurité personnalisé et que vous l’utilisez comme jeton principal, WCF dérive une clé de celui-ci. Ce faisant, il appelle le sérialiseur de jeton de sécurité personnalisé afin d'écrire SecurityKeyIdentifierClause pour le jeton de sécurité personnalisé pendant la sérialisation du DerivedKeyToken
sur le câble. À l'extrémité de réception, lors de la désérialisation du jeton du câble, le sérialiseur DerivedKeyToken
attend un élément SecurityTokenReference
en tant qu'enfant de niveau supérieur au-dessous de lui. Si le sérialiseur de jeton de sécurité personnalisé n'a pas ajouté d'élément SecurityTokenReference
pendant la sérialisation de son type de clause, une exception est levée.
Définissez une nouvelle classe dérivée de la classe WSSecurityTokenSerializer.
Remplacez la méthode CanReadTokenCore(XmlReader). Elle utilise un XmlReader pour lire le flux XML. Cette méthode retourne true
si l'implémentation du sérialiseur peut désérialiser le jeton de sécurité en fonction de l'élément en cours. Dans cet exemple, cette méthode vérifie si le nom et l'espace de noms de l'élément XML en cours du lecteur XML sont corrects. Dans le cas contraire, elle appelle l'implémentation de classe de base de cette méthode pour gérer l'élément XML.
Remplacez la méthode ReadTokenCore(XmlReader, SecurityTokenResolver) . Cette méthode lit le contenu XML de jeton de sécurité et construit la représentation en mémoire adéquate lui correspondant. Si elle ne reconnaît pas l'élément XML du lecteur XML passé, elle appelle l'implémentation de base pour traiter les types de jeton fournis par le système.
Remplacez la méthode CanWriteTokenCore(SecurityToken) . Cette méthode retourne true
si elle peut convertir la représentation en mémoire du jeton (passée sous forme d'argument) en représentation XML. Dans le cas contraire, elle appelle l'implémentation de la classe de base.
Remplacez la méthode WriteTokenCore(XmlWriter, SecurityToken) . Cette méthode convertit la représentation en mémoire du jeton de sécurité en représentation XML. Si elle ne peut pas effectuer la conversion, elle appelle l'implémentation de la classe de base.
public class CreditCardSecurityTokenSerializer : WSSecurityTokenSerializer
{
public CreditCardSecurityTokenSerializer(SecurityTokenVersion version) : base() { }
protected override bool CanReadTokenCore(XmlReader reader)
{
XmlDictionaryReader localReader = XmlDictionaryReader.CreateDictionaryReader(reader);
if (reader == null)
{
throw new ArgumentNullException("reader");
}
if (reader.IsStartElement(Constants.CreditCardTokenName, Constants.CreditCardTokenNamespace))
{
return true;
}
return base.CanReadTokenCore(reader);
}
protected override SecurityToken ReadTokenCore(XmlReader reader, SecurityTokenResolver tokenResolver)
{
if (reader == null)
{
throw new ArgumentNullException("reader");
}
if (reader.IsStartElement(Constants.CreditCardTokenName, Constants.CreditCardTokenNamespace))
{
string id = reader.GetAttribute(Constants.Id, Constants.WsUtilityNamespace);
reader.ReadStartElement();
// Read the credit card number.
string creditCardNumber = reader.ReadElementString(Constants.CreditCardNumberElementName, Constants.CreditCardTokenNamespace);
// Read the expiration date.
string expirationTimeString = reader.ReadElementString(Constants.CreditCardExpirationElementName, Constants.CreditCardTokenNamespace);
DateTime expirationTime = XmlConvert.ToDateTime(expirationTimeString, XmlDateTimeSerializationMode.Utc);
// Read the issuer of the credit card.
string creditCardIssuer = reader.ReadElementString(Constants.CreditCardIssuerElementName, Constants.CreditCardTokenNamespace);
reader.ReadEndElement();
CreditCardInfo cardInfo = new CreditCardInfo(creditCardNumber, creditCardIssuer, expirationTime);
return new CreditCardToken(cardInfo, id);
}
else
{
return WSSecurityTokenSerializer.DefaultInstance.ReadToken(reader, tokenResolver);
}
}
protected override bool CanWriteTokenCore(SecurityToken token)
{
if (token is CreditCardToken)
{
return true;
}
else
{
return base.CanWriteTokenCore(token);
}
}
protected override void WriteTokenCore(XmlWriter writer, SecurityToken token)
{
if (writer == null)
{
throw new ArgumentNullException("writer");
}
if (token == null)
{
throw new ArgumentNullException("token");
}
CreditCardToken c = token as CreditCardToken;
if (c != null)
{
writer.WriteStartElement(Constants.CreditCardTokenPrefix, Constants.CreditCardTokenName, Constants.CreditCardTokenNamespace);
writer.WriteAttributeString(Constants.WsUtilityPrefix, Constants.Id, Constants.WsUtilityNamespace, token.Id);
writer.WriteElementString(Constants.CreditCardNumberElementName, Constants.CreditCardTokenNamespace, c.CardInfo.CardNumber);
writer.WriteElementString(Constants.CreditCardExpirationElementName, Constants.CreditCardTokenNamespace, XmlConvert.ToString(c.CardInfo.ExpirationDate, XmlDateTimeSerializationMode.Utc));
writer.WriteElementString(Constants.CreditCardIssuerElementName, Constants.CreditCardTokenNamespace, c.CardInfo.CardIssuer);
writer.WriteEndElement();
writer.Flush();
}
else
{
base.WriteTokenCore(writer, token);
}
}
}
Public Class CreditCardSecurityTokenSerializer
Inherits WSSecurityTokenSerializer
Public Sub New(ByVal version As SecurityTokenVersion)
MyBase.New()
End Sub
Protected Overrides Function CanReadTokenCore(ByVal reader As XmlReader) As Boolean
Dim localReader = XmlDictionaryReader.CreateDictionaryReader(reader)
If reader Is Nothing Then
Throw New ArgumentNullException("reader")
End If
If reader.IsStartElement(Constants.CreditCardTokenName, _
Constants.CreditCardTokenNamespace) Then
Return True
End If
Return MyBase.CanReadTokenCore(reader)
End Function
Protected Overrides Function ReadTokenCore(ByVal reader As XmlReader, _
ByVal tokenResolver As SecurityTokenResolver) As SecurityToken
If reader Is Nothing Then
Throw New ArgumentNullException("reader")
End If
If reader.IsStartElement(Constants.CreditCardTokenName, _
Constants.CreditCardTokenNamespace) Then
Dim id = reader.GetAttribute(Constants.Id, _
Constants.WsUtilityNamespace)
reader.ReadStartElement()
' Read the credit card number.
Dim creditCardNumber = reader.ReadElementString(Constants.CreditCardNumberElementName, _
Constants.CreditCardTokenNamespace)
' Read the expiration date.
Dim expirationTimeString = reader.ReadElementString(Constants.CreditCardExpirationElementName, _
Constants.CreditCardTokenNamespace)
Dim expirationTime As DateTime = XmlConvert.ToDateTime(expirationTimeString, _
XmlDateTimeSerializationMode.Utc)
' Read the issuer of the credit card.
Dim creditCardIssuer = reader.ReadElementString(Constants.CreditCardIssuerElementName, _
Constants.CreditCardTokenNamespace)
reader.ReadEndElement()
Dim cardInfo As New CreditCardInfo(creditCardNumber, _
creditCardIssuer, _
expirationTime)
Return New CreditCardToken(cardInfo, id)
Else
Return WSSecurityTokenSerializer.DefaultInstance.ReadToken(reader, _
tokenResolver)
End If
End Function
Protected Overrides Function CanWriteTokenCore(ByVal token As SecurityToken) As Boolean
If TypeOf token Is CreditCardToken Then
Return True
Else
Return MyBase.CanWriteTokenCore(token)
End If
End Function
Protected Overrides Sub WriteTokenCore(ByVal writer As XmlWriter, _
ByVal token As SecurityToken)
If writer Is Nothing Then
Throw New ArgumentNullException("writer")
End If
If token Is Nothing Then
Throw New ArgumentNullException("token")
End If
Dim c = TryCast(token, CreditCardToken)
If c IsNot Nothing Then
With writer
.WriteStartElement(Constants.CreditCardTokenPrefix, _
Constants.CreditCardTokenName, _
Constants.CreditCardTokenNamespace)
.WriteAttributeString(Constants.WsUtilityPrefix, _
Constants.Id, _
Constants.WsUtilityNamespace, _
token.Id)
.WriteElementString(Constants.CreditCardNumberElementName, _
Constants.CreditCardTokenNamespace, _
c.CardInfo.CardNumber)
.WriteElementString(Constants.CreditCardExpirationElementName, _
Constants.CreditCardTokenNamespace, _
XmlConvert.ToString(c.CardInfo.ExpirationDate, _
XmlDateTimeSerializationMode.Utc))
.WriteElementString(Constants.CreditCardIssuerElementName, _
Constants.CreditCardTokenNamespace, _
c.CardInfo.CardIssuer)
.WriteEndElement()
.Flush()
End With
Else
MyBase.WriteTokenCore(writer, token)
End If
End Sub
End Class
Les quatre procédures ci-dessus effectuées, intégrez le jeton de sécurité personnalisé au fournisseur, authentificateur et gestionnaire de jetons de sécurité ainsi qu'aux informations d'identification client et service.
Le fournisseur de jeton de sécurité crée, modifie (si nécessaire) et retourne une instance du jeton. Pour créer un fournisseur de jetons de sécurité pour le jeton de sécurité personnalisé, créez une classe qui hérite de la classe SecurityTokenProvider. L'exemple suivant remplace la méthode GetTokenCore pour retourner une instance de CreditCardToken
. Pour plus d’informations sur les fournisseurs de jetons de sécurité personnalisés, consultez Guide pratique pour créer un fournisseur de jetons de sécurité personnalisé.
class CreditCardTokenProvider : SecurityTokenProvider
{
CreditCardInfo creditCardInfo;
public CreditCardTokenProvider(CreditCardInfo creditCardInfo)
: base()
{
if (creditCardInfo == null)
{
throw new ArgumentNullException("creditCardInfo");
}
this.creditCardInfo = creditCardInfo;
}
protected override SecurityToken GetTokenCore(TimeSpan timeout)
{
SecurityToken result = new CreditCardToken(this.creditCardInfo);
return result;
}
}
Friend Class CreditCardTokenProvider
Inherits SecurityTokenProvider
Private creditCardInfo As CreditCardInfo
Public Sub New(ByVal creditCardInfo As CreditCardInfo)
MyBase.New()
If creditCardInfo Is Nothing Then
Throw New ArgumentNullException("creditCardInfo")
End If
Me.creditCardInfo = creditCardInfo
End Sub
Protected Overrides Function GetTokenCore(ByVal timeout As TimeSpan) As SecurityToken
Return TryCast(New CreditCardToken(Me.creditCardInfo), SecurityToken)
End Function
End Class
L'authentificateur de jetons de sécurité valide le contenu du jeton de sécurité lorsque ce dernier est extrait du message. Pour créer un authentificateur personnalisé pour le jeton de sécurité personnalisé, créez une classe qui hérite de la classe SecurityTokenAuthenticator. L'exemple suivant substitue la méthode ValidateTokenCore. Pour plus d’informations sur les authentificateurs de jeton de sécurité personnalisés, consultez Guide pratique pour créer un authentificateur de jetons de sécurité personnalisé.
class CreditCardTokenAuthenticator : SecurityTokenAuthenticator
{
string creditCardsFile;
public CreditCardTokenAuthenticator(string creditCardsFile)
{
this.creditCardsFile = creditCardsFile;
}
protected override bool CanValidateTokenCore(SecurityToken token)
{
return (token is CreditCardToken);
}
protected override ReadOnlyCollection<IAuthorizationPolicy> ValidateTokenCore(SecurityToken token)
{
CreditCardToken creditCardToken = token as CreditCardToken;
if (creditCardToken.CardInfo.ExpirationDate < DateTime.UtcNow)
{
throw new SecurityTokenValidationException("The credit card has expired");
}
if (!IsCardNumberAndExpirationValid(creditCardToken.CardInfo))
{
throw new SecurityTokenValidationException("Unknown or invalid credit card");
}
// The credit card token has only 1 claim: the card number. The issuer for the claim is the
// credit card issuer.
DefaultClaimSet cardIssuerClaimSet = new DefaultClaimSet(new Claim(ClaimTypes.Name, creditCardToken.CardInfo.CardIssuer, Rights.PossessProperty));
DefaultClaimSet cardClaimSet = new DefaultClaimSet(cardIssuerClaimSet, new Claim(Constants.CreditCardNumberClaim, creditCardToken.CardInfo.CardNumber, Rights.PossessProperty));
List<IAuthorizationPolicy> policies = new List<IAuthorizationPolicy>(1);
policies.Add(new CreditCardTokenAuthorizationPolicy(cardClaimSet));
return policies.AsReadOnly();
}
// This helper method checks whether a given credit card entry is present in the user database.
private bool IsCardNumberAndExpirationValid(CreditCardInfo cardInfo)
{
try
{
using (StreamReader myStreamReader = new StreamReader(this.creditCardsFile))
{
string line = "";
while ((line = myStreamReader.ReadLine()) != null)
{
string[] splitEntry = line.Split('#');
if (splitEntry[0] == cardInfo.CardNumber)
{
string expirationDateString = splitEntry[1].Trim();
DateTime expirationDateOnFile = DateTime.Parse(expirationDateString, System.Globalization.DateTimeFormatInfo.InvariantInfo, System.Globalization.DateTimeStyles.AdjustToUniversal);
if (cardInfo.ExpirationDate == expirationDateOnFile)
{
string issuer = splitEntry[2];
return issuer.Equals(cardInfo.CardIssuer, StringComparison.InvariantCultureIgnoreCase);
}
else
{
return false;
}
}
}
return false;
}
}
catch (Exception e)
{
throw new Exception("BookStoreService: Error while retrieving credit card information from User DB " + e.ToString());
}
}
}
Friend Class CreditCardTokenAuthenticator
Inherits SecurityTokenAuthenticator
Private creditCardsFile As String
Public Sub New(ByVal creditCardsFile As String)
Me.creditCardsFile = creditCardsFile
End Sub
Protected Overrides Function CanValidateTokenCore(ByVal token As SecurityToken) As Boolean
Return (TypeOf token Is CreditCardToken)
End Function
Protected Overrides Function ValidateTokenCore(ByVal token As SecurityToken) As ReadOnlyCollection(Of IAuthorizationPolicy)
Dim creditCardToken = TryCast(token, CreditCardToken)
If creditCardToken.CardInfo.ExpirationDate < DateTime.UtcNow Then
Throw New SecurityTokenValidationException("The credit card has expired")
End If
If Not IsCardNumberAndExpirationValid(creditCardToken.CardInfo) Then
Throw New SecurityTokenValidationException("Unknown or invalid credit card")
End If
' The credit card token has only 1 claim: the card number. The issuer for the claim is the
' credit card issuer.
Dim cardIssuerClaimSet As New DefaultClaimSet(New Claim(ClaimTypes.Name, _
creditCardToken.CardInfo.CardIssuer, _
Rights.PossessProperty))
Dim cardClaimSet As New DefaultClaimSet(cardIssuerClaimSet, _
New Claim(Constants.CreditCardNumberClaim, _
creditCardToken.CardInfo.CardNumber, _
Rights.PossessProperty))
Dim policies As New List(Of IAuthorizationPolicy)(1)
policies.Add(New CreditCardTokenAuthorizationPolicy(cardClaimSet))
Return policies.AsReadOnly()
End Function
' This helper method checks whether a given credit card entry is present in the user database.
Private Function IsCardNumberAndExpirationValid(ByVal cardInfo As CreditCardInfo) As Boolean
Try
Using myStreamReader As New StreamReader(Me.creditCardsFile)
Dim line = String.Empty
line = myStreamReader.ReadLine()
Do While line IsNot Nothing
Dim splitEntry() = line.Split("#"c)
If splitEntry(0) = cardInfo.CardNumber Then
Dim expirationDateString = splitEntry(1).Trim()
Dim expirationDateOnFile As DateTime = DateTime.Parse(expirationDateString, _
System.Globalization.DateTimeFormatInfo.InvariantInfo, _
System.Globalization.DateTimeStyles.AdjustToUniversal)
If cardInfo.ExpirationDate = expirationDateOnFile Then
Dim issuer = splitEntry(2)
Return issuer.Equals(cardInfo.CardIssuer, _
StringComparison.InvariantCultureIgnoreCase)
Else
Return False
End If
End If
line = myStreamReader.ReadLine()
Loop
Return False
End Using
Catch e As Exception
Throw New Exception("BookStoreService: Error while retrieving credit card information from User DB " & e.ToString())
End Try
End Function
End Class
public class CreditCardTokenAuthorizationPolicy : IAuthorizationPolicy
{
string id;
ClaimSet issuer;
IEnumerable<ClaimSet> issuedClaimSets;
public CreditCardTokenAuthorizationPolicy(ClaimSet issuedClaims)
{
if (issuedClaims == null)
throw new ArgumentNullException("issuedClaims");
this.issuer = issuedClaims.Issuer;
this.issuedClaimSets = new ClaimSet[] { issuedClaims };
this.id = Guid.NewGuid().ToString();
}
public ClaimSet Issuer { get { return this.issuer; } }
public string Id { get { return this.id; } }
public bool Evaluate(EvaluationContext context, ref object state)
{
foreach (ClaimSet issuance in this.issuedClaimSets)
{
context.AddClaimSet(this, issuance);
}
return true;
}
}
Public Class CreditCardTokenAuthorizationPolicy
Implements IAuthorizationPolicy
Private _id As String
Private _issuer As ClaimSet
Private _issuedClaimSets As IEnumerable(Of ClaimSet)
Public Sub New(ByVal issuedClaims As ClaimSet)
If issuedClaims Is Nothing Then
Throw New ArgumentNullException("issuedClaims")
End If
Me._issuer = issuedClaims.Issuer
Me._issuedClaimSets = New ClaimSet() {issuedClaims}
Me._id = Guid.NewGuid().ToString()
End Sub
Public ReadOnly Property Issuer() As ClaimSet Implements IAuthorizationPolicy.Issuer
Get
Return Me._issuer
End Get
End Property
Public ReadOnly Property Id() As String Implements System.IdentityModel.Policy.IAuthorizationComponent.Id
Get
Return Me._id
End Get
End Property
Public Function Evaluate(ByVal context As EvaluationContext, _
ByRef state As Object) As Boolean Implements IAuthorizationPolicy.Evaluate
For Each issuance In Me._issuedClaimSets
context.AddClaimSet(Me, issuance)
Next issuance
Return True
End Function
End Class
Le gestionnaire de jetons de sécurité crée les instances de fournisseur, d'authentificateur et de sérialiseur de jetons de sécurité appropriées. Pour créer un gestionnaire de jetons de sécurité personnalisé, créez une classe qui hérite de la classe ClientCredentialsSecurityTokenManager. Les principales méthodes de la classe utilisent une spécification SecurityTokenRequirement pour créer le fournisseur approprié ainsi que les informations d'identification client ou service requises. Pour plus d’informations sur les gestionnaires de jetons de sécurité personnalisés, consultez la Procédure pas à pas : Création d’informations d’identification de client et de service personnalisées.
public class CreditCardClientCredentialsSecurityTokenManager : ClientCredentialsSecurityTokenManager
{
CreditCardClientCredentials creditCardClientCredentials;
public CreditCardClientCredentialsSecurityTokenManager(CreditCardClientCredentials creditCardClientCredentials)
: base(creditCardClientCredentials)
{
this.creditCardClientCredentials = creditCardClientCredentials;
}
public override SecurityTokenProvider CreateSecurityTokenProvider(SecurityTokenRequirement tokenRequirement)
{
if (tokenRequirement.TokenType == Constants.CreditCardTokenType)
{
// Handle this token for Custom.
return new CreditCardTokenProvider(this.creditCardClientCredentials.CreditCardInfo);
}
else if (tokenRequirement is InitiatorServiceModelSecurityTokenRequirement)
{
// Return server certificate.
if (tokenRequirement.TokenType == SecurityTokenTypes.X509Certificate)
{
return new X509SecurityTokenProvider(creditCardClientCredentials.ServiceCertificate.DefaultCertificate);
}
}
return base.CreateSecurityTokenProvider(tokenRequirement);
}
public override SecurityTokenSerializer CreateSecurityTokenSerializer(SecurityTokenVersion version)
{
return new CreditCardSecurityTokenSerializer(version);
}
}
Public Class CreditCardClientCredentialsSecurityTokenManager
Inherits ClientCredentialsSecurityTokenManager
Private creditCardClientCredentials As CreditCardClientCredentials
Public Sub New(ByVal creditCardClientCredentials As CreditCardClientCredentials)
MyBase.New(creditCardClientCredentials)
Me.creditCardClientCredentials = creditCardClientCredentials
End Sub
Public Overrides Function CreateSecurityTokenProvider(ByVal tokenRequirement As SecurityTokenRequirement) As SecurityTokenProvider
If tokenRequirement.TokenType = Constants.CreditCardTokenType Then
' Handle this token for Custom.
Return New CreditCardTokenProvider(Me.creditCardClientCredentials.CreditCardInfo)
ElseIf TypeOf tokenRequirement Is InitiatorServiceModelSecurityTokenRequirement Then
' Return server certificate.
If tokenRequirement.TokenType = SecurityTokenTypes.X509Certificate Then
Return New X509SecurityTokenProvider(creditCardClientCredentials.ServiceCertificate.DefaultCertificate)
End If
End If
Return MyBase.CreateSecurityTokenProvider(tokenRequirement)
End Function
Public Overloads Overrides Function CreateSecurityTokenSerializer(ByVal version As SecurityTokenVersion) As SecurityTokenSerializer
Return New CreditCardSecurityTokenSerializer(version)
End Function
End Class
public class CreditCardServiceCredentialsSecurityTokenManager : ServiceCredentialsSecurityTokenManager
{
CreditCardServiceCredentials creditCardServiceCredentials;
public CreditCardServiceCredentialsSecurityTokenManager(CreditCardServiceCredentials creditCardServiceCredentials)
: base(creditCardServiceCredentials)
{
this.creditCardServiceCredentials = creditCardServiceCredentials;
}
public override SecurityTokenAuthenticator CreateSecurityTokenAuthenticator(SecurityTokenRequirement tokenRequirement, out SecurityTokenResolver outOfBandTokenResolver)
{
if (tokenRequirement.TokenType == Constants.CreditCardTokenType)
{
outOfBandTokenResolver = null;
return new CreditCardTokenAuthenticator(creditCardServiceCredentials.CreditCardDataFile);
}
return base.CreateSecurityTokenAuthenticator(tokenRequirement, out outOfBandTokenResolver);
}
public override SecurityTokenSerializer CreateSecurityTokenSerializer(SecurityTokenVersion version)
{
return new CreditCardSecurityTokenSerializer(version);
}
}
Public Class CreditCardServiceCredentialsSecurityTokenManager
Inherits ServiceCredentialsSecurityTokenManager
Private creditCardServiceCredentials As CreditCardServiceCredentials
Public Sub New(ByVal creditCardServiceCredentials As CreditCardServiceCredentials)
MyBase.New(creditCardServiceCredentials)
Me.creditCardServiceCredentials = creditCardServiceCredentials
End Sub
Public Overrides Function CreateSecurityTokenAuthenticator(ByVal tokenRequirement As SecurityTokenRequirement, _
<System.Runtime.InteropServices.Out()> ByRef outOfBandTokenResolver As SecurityTokenResolver) As SecurityTokenAuthenticator
If tokenRequirement.TokenType = Constants.CreditCardTokenType Then
outOfBandTokenResolver = Nothing
Return New CreditCardTokenAuthenticator(creditCardServiceCredentials.CreditCardDataFile)
End If
Return MyBase.CreateSecurityTokenAuthenticator(tokenRequirement, outOfBandTokenResolver)
End Function
Public Overrides Function CreateSecurityTokenSerializer(ByVal version As SecurityTokenVersion) As SecurityTokenSerializer
Return New CreditCardSecurityTokenSerializer(version)
End Function
End Class
Les informations d'identification client et service doivent être ajoutées afin de générer une API pour l'application. Cette API permet de spécifier les informations du jeton de sécurité personnalisé qui seront utilisées par l'infrastructure de ce dernier créée précédemment afin de générer son contenu et de l'authentifier. Les exemples suivants montrent comment procéder. Pour plus d’informations sur les informations d’identification de client et de service personnalisées, consultez la Procédure pas à pas : Création d’informations d’identification de client et de service personnalisées.
public class CreditCardClientCredentials : ClientCredentials
{
CreditCardInfo creditCardInfo;
public CreditCardClientCredentials(CreditCardInfo creditCardInfo)
: base()
{
if (creditCardInfo == null)
{
throw new ArgumentNullException("creditCardInfo");
}
this.creditCardInfo = creditCardInfo;
}
public CreditCardInfo CreditCardInfo
{
get { return this.creditCardInfo; }
}
protected override ClientCredentials CloneCore()
{
return new CreditCardClientCredentials(this.creditCardInfo);
}
public override SecurityTokenManager CreateSecurityTokenManager()
{
return new CreditCardClientCredentialsSecurityTokenManager(this);
}
}
Public Class CreditCardClientCredentials
Inherits ClientCredentials
Private _creditCardInfo As CreditCardInfo
Public Sub New(ByVal creditCardInfo As CreditCardInfo)
MyBase.New()
If creditCardInfo Is Nothing Then
Throw New ArgumentNullException("creditCardInfo")
End If
Me._creditCardInfo = creditCardInfo
End Sub
Public ReadOnly Property CreditCardInfo() As CreditCardInfo
Get
Return Me._creditCardInfo
End Get
End Property
Protected Overrides Function CloneCore() As ClientCredentials
Return New CreditCardClientCredentials(Me._creditCardInfo)
End Function
Public Overrides Function CreateSecurityTokenManager() As SecurityTokenManager
Return New CreditCardClientCredentialsSecurityTokenManager(Me)
End Function
End Class
public class CreditCardServiceCredentials : ServiceCredentials
{
string creditCardFile;
public CreditCardServiceCredentials(string creditCardFile)
: base()
{
if (creditCardFile == null)
{
throw new ArgumentNullException("creditCardFile");
}
this.creditCardFile = creditCardFile;
}
public string CreditCardDataFile
{
get { return this.creditCardFile; }
}
protected override ServiceCredentials CloneCore()
{
return new CreditCardServiceCredentials(this.creditCardFile);
}
public override SecurityTokenManager CreateSecurityTokenManager()
{
return new CreditCardServiceCredentialsSecurityTokenManager(this);
}
}
Public Class CreditCardServiceCredentials
Inherits ServiceCredentials
Private creditCardFile As String
Public Sub New(ByVal creditCardFile As String)
MyBase.New()
If creditCardFile Is Nothing Then
Throw New ArgumentNullException("creditCardFile")
End If
Me.creditCardFile = creditCardFile
End Sub
Public ReadOnly Property CreditCardDataFile() As String
Get
Return Me.creditCardFile
End Get
End Property
Protected Overrides Function CloneCore() As ServiceCredentials
Return New CreditCardServiceCredentials(Me.creditCardFile)
End Function
Public Overrides Function CreateSecurityTokenManager() As SecurityTokenManager
Return New CreditCardServiceCredentialsSecurityTokenManager(Me)
End Function
End Class
La classe de paramètres de jeton de sécurité personnalisé créée précédemment est utilisée pour indiquer au framework de sécurité WCF qu’un jeton de sécurité personnalisé doit être utilisé lors de la communication avec un service. La procédure suivante indique comment effectuer cette opération.
La classe de paramètres de jeton de sécurité personnalisé doit être spécifiée dans l'une des collections de paramètres de jeton exposées sur la classe SecurityBindingElement. Dans l'exemple suivant, la collection retournée par SignedEncrypted
est utilisée. Le code ajoute un jeton personnalisé de carte de crédit à tous les messages envoyés depuis le client au service, le contenu de ce jeton étant automatiquement signé et chiffré.
public static class BindingHelper
{
public static Binding CreateCreditCardBinding()
{
HttpTransportBindingElement httpTransport = new HttpTransportBindingElement();
// The message security binding element is configured to require a credit card
// token that is encrypted with the service's certificate.
SymmetricSecurityBindingElement messageSecurity = new SymmetricSecurityBindingElement();
messageSecurity.EndpointSupportingTokenParameters.SignedEncrypted.Add(new CreditCardTokenParameters());
X509SecurityTokenParameters x509ProtectionParameters = new X509SecurityTokenParameters();
x509ProtectionParameters.InclusionMode = SecurityTokenInclusionMode.Never;
messageSecurity.ProtectionTokenParameters = x509ProtectionParameters;
return new CustomBinding(messageSecurity, httpTransport);
}
}
Public NotInheritable Class BindingHelper
Private Sub New()
End Sub
Public Shared Function CreateCreditCardBinding() As Binding
Dim httpTransport As New HttpTransportBindingElement()
' The message security binding element is configured to require a credit card
' token that is encrypted with the service's certificate.
Dim messageSecurity As New SymmetricSecurityBindingElement()
messageSecurity.EndpointSupportingTokenParameters.SignedEncrypted.Add(New CreditCardTokenParameters())
Dim x509ProtectionParameters As New X509SecurityTokenParameters()
x509ProtectionParameters.InclusionMode = SecurityTokenInclusionMode.Never
messageSecurity.ProtectionTokenParameters = x509ProtectionParameters
Return New CustomBinding(messageSecurity, httpTransport)
End Function
End Class
Cette rubrique décrit les différents éléments de code nécessaires à l'implémentation et l'utilisation d'un jeton personnalisé. Pour voir un exemple complet de la façon dont tous ces éléments de code s’ajustent les uns aux autres, consultez Jeton personnalisé.
Événements
Créer des applications intelligentes
17 mars, 21 h - 21 mars, 10 h
Rejoignez la série de rencontres pour créer des solutions IA évolutives basées sur des cas d’usage réels avec d’autres développeurs et experts.
S’inscrire maintenantEntrainement
Module
Concevoir des solutions d’authentification et d’autorisation - Training
Les architectes Azure conçoivent et recommandent des solutions d’authentification et d’autorisation.