Procedure: Een aangepast token maken
In dit onderwerp wordt beschreven hoe u een aangepast beveiligingstoken maakt met behulp van de SecurityToken klasse en hoe u dit kunt integreren met een aangepaste beveiligingstokenprovider en verificator. Zie het voorbeeld van het aangepaste token voor een volledig codevoorbeeld.
Een beveiligingstoken is in feite een XML-element dat wordt gebruikt door het WCF-beveiligingsframework (Windows Communication Foundation) om claims over een afzender in het SOAP-bericht weer te geven. WCF-beveiliging biedt verschillende tokens voor door het systeem geleverde verificatiemodi. Voorbeelden hiervan zijn een X.509-certificaatbeveiligingstoken dat wordt vertegenwoordigd door de X509SecurityToken klasse of een gebruikersnaambeveiligingstoken dat wordt vertegenwoordigd door de UserNameSecurityToken klasse.
Soms wordt een verificatiemodus of referentie niet ondersteund door de opgegeven typen. In dat geval moet u een aangepast beveiligingstoken maken om een XML-weergave van de aangepaste referenties in het SOAP-bericht op te geven.
De volgende procedures laten zien hoe u een aangepast beveiligingstoken maakt en hoe u dit integreert met de WCF-beveiligingsinfrastructuur. In dit onderwerp wordt een creditcardtoken gemaakt dat wordt gebruikt om informatie over de creditcard van de client door te geven aan de server.
Zie Overzicht: Aangepaste client- en servicereferenties maken voor meer informatie over aangepaste referenties en beveiligingstokenbeheer.
Zie de System.IdentityModel.Tokens naamruimte voor meer klassen die beveiligingstokens vertegenwoordigen.
Procedures
Er moet een clienttoepassing worden geleverd met een manier om creditcardgegevens voor de beveiligingsinfrastructuur op te geven. Deze informatie wordt beschikbaar gesteld aan de toepassing door een aangepaste clientreferentieklasse. De eerste stap is het maken van een klasse om de creditcardgegevens voor aangepaste clientreferenties weer te geven.
Een klasse maken die creditcardgegevens in clientreferenties vertegenwoordigt
Definieer een nieuwe klasse die de creditcardgegevens voor de toepassing vertegenwoordigt. In het volgende voorbeeld wordt de klasse
CreditCardInfo
genoemd.Voeg de juiste eigenschappen toe aan de klasse om toe te staan dat een toepassing de benodigde gegevens voor het aangepaste token instelt. In dit voorbeeld heeft de klasse drie eigenschappen:
CardNumber
,CardIssuer
enExpirationDate
.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
Vervolgens moet er een klasse worden gemaakt die het aangepaste beveiligingstoken vertegenwoordigt. Deze klasse wordt gebruikt door de beveiligingstokenprovider, verificator- en serializer-klassen om informatie over het beveiligingstoken door te geven aan en van de WCF-beveiligingsinfrastructuur.
Een aangepaste beveiligingstokenklasse maken
Definieer een nieuwe klasse die is afgeleid van de SecurityToken klasse. In dit voorbeeld wordt een klasse met de naam
CreditCardToken
gemaakt.Overschrijf de Id eigenschap. Deze eigenschap wordt gebruikt om de lokale id op te halen van het beveiligingstoken dat wordt gebruikt om te verwijzen naar de XML-weergave van het beveiligingstoken van andere elementen in het SOAP-bericht. In dit voorbeeld kan een token-id worden doorgegeven als een constructorparameter of een nieuwe willekeurige wordt gegenereerd telkens wanneer een exemplaar van een beveiligingstoken wordt gemaakt.
Implementeer de SecurityKeys eigenschap. Deze eigenschap retourneert een verzameling beveiligingssleutels die het exemplaar van het beveiligingstoken vertegenwoordigt. Dergelijke sleutels kunnen door WCF worden gebruikt om delen van het SOAP-bericht te ondertekenen of te versleutelen. In dit voorbeeld mag het token voor creditcardbeveiliging geen beveiligingssleutels bevatten; daarom retourneert de implementatie altijd een lege verzameling.
Overschrijf de ValidFrom en ValidTo eigenschappen. Deze eigenschappen worden door WCF gebruikt om de geldigheid van het beveiligingstokenexemplaren te bepalen. In dit voorbeeld heeft het beveiligingstoken voor creditcards slechts een vervaldatum, dus retourneert de
ValidFrom
eigenschap een DateTime waarde die de datum en tijd aangeeft waarop het exemplaar is gemaakt.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
Wanneer er een nieuw type beveiligingstoken wordt gemaakt, is een implementatie van de SecurityTokenParameters klasse vereist. De implementatie wordt gebruikt in de configuratie van het beveiligingsbindingselement om het nieuwe tokentype weer te geven. De klasse beveiligingstokenparameters fungeert als een sjabloon die wordt gebruikt om het werkelijke exemplaar van het beveiligingstoken te koppelen aan wanneer een bericht wordt verwerkt. De sjabloon bevat aanvullende eigenschappen die een toepassing kan gebruiken om criteria op te geven die overeenkomen met het beveiligingstoken dat moet worden gebruikt of geverifieerd. In het volgende voorbeeld worden geen extra eigenschappen toegevoegd, dus alleen het type beveiligingstoken wordt vergeleken wanneer de WCF-infrastructuur zoekt naar een exemplaar van een beveiligingstoken dat moet worden gebruikt of gevalideerd.
Een aangepaste beveiligingstokenparametersklasse maken
Definieer een nieuwe klasse die is afgeleid van de SecurityTokenParameters klasse.
Implementeer de CloneCore methode. Kopieer alle interne velden die in uw klas zijn gedefinieerd, indien van toepassing. In dit voorbeeld worden geen extra velden gedefinieerd.
Implementeer de SupportsClientAuthentication eigenschap Alleen-lezen. Deze eigenschap retourneert
true
als het beveiligingstokentype dat door deze klasse wordt vertegenwoordigd, kan worden gebruikt om een client te verifiëren bij een service. In dit voorbeeld kan het beveiligingstoken voor creditcards worden gebruikt om een client te verifiëren bij een service.Implementeer de SupportsServerAuthentication eigenschap Alleen-lezen. Deze eigenschap retourneert
true
als het beveiligingstokentype dat door deze klasse wordt vertegenwoordigd, kan worden gebruikt om een service te verifiëren bij een client. In dit voorbeeld kan het beveiligingstoken voor creditcards niet worden gebruikt voor het verifiëren van een service voor een client.Implementeer de SupportsClientWindowsIdentity eigenschap Alleen-lezen. Deze eigenschap retourneert
true
als het beveiligingstokentype dat door deze klasse wordt vertegenwoordigd, kan worden toegewezen aan een Windows-account. Als dit het geval is, wordt het verificatieresultaat vertegenwoordigd door een WindowsIdentity klasse-exemplaar. In dit voorbeeld kan het token niet worden toegewezen aan een Windows-account.Implementeer de CreateKeyIdentifierClause(SecurityToken, SecurityTokenReferenceStyle) methode. Deze methode wordt aangeroepen door het WCF-beveiligingsframework wanneer er een verwijzing naar het beveiligingstokenexemplaren is vereist die wordt vertegenwoordigd door deze beveiligingstokenparametersklasse. Zowel het werkelijke exemplaar van het beveiligingstoken als SecurityTokenReferenceStyle het type verwijzing dat wordt aangevraagd, wordt als argumenten doorgegeven aan deze methode. In dit voorbeeld worden alleen interne verwijzingen ondersteund door het beveiligingstoken voor creditcards. De SecurityToken klasse heeft functionaliteit om interne verwijzingen te maken. De implementatie vereist daarom geen extra code.
Implementeer de InitializeSecurityTokenRequirement(SecurityTokenRequirement) methode. Deze methode wordt aangeroepen door WCF om het exemplaar van de beveiligingstokenparametersklasse te converteren naar een exemplaar van de SecurityTokenRequirement klasse. Het resultaat wordt gebruikt door beveiligingstokenproviders om het juiste beveiligingstokenexemplaren te maken.
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
Beveiligingstokens worden verzonden in SOAP-berichten. Hiervoor is een vertaalmechanisme vereist tussen de in-memory beveiligingstokenweergave en de on-the-wire-weergave. WCF gebruikt een serialisatiefunctie voor beveiligingstokens om deze taak uit te voeren. Elk aangepast token moet worden vergezeld van een aangepaste serialisatiefunctie voor beveiligingstokens waarmee het aangepaste beveiligingstoken kan worden geserialiseerd en gedeserialiseerd vanuit het SOAP-bericht.
Notitie
Afgeleide sleutels zijn standaard ingeschakeld. Als u een aangepast beveiligingstoken maakt en dit als primair token gebruikt, wordt door WCF een sleutel afgeleid. Hierbij wordt de serialisatiefunctie voor het aangepaste beveiligingstoken aanroepen om het SecurityKeyIdentifierClause voor het aangepaste beveiligingstoken te schrijven terwijl de DerivedKeyToken
token naar de kabel wordt geserialiseerd. Bij het deserialiseren van het token van de draad verwacht de DerivedKeyToken
serializer een SecurityTokenReference
element als het onderliggende element op het hoogste niveau onder zichzelf. Als de aangepaste beveiligingstokenserialisatie geen SecurityTokenReference
element heeft toegevoegd tijdens het serialiseren van het componenttype, wordt er een uitzondering gegenereerd.
Een aangepaste serialisatiefunctie voor beveiligingstokens maken
Definieer een nieuwe klasse die is afgeleid van de WSSecurityTokenSerializer klasse.
Overschrijf de CanReadTokenCore(XmlReader) methode, die afhankelijk is van een XmlReader om de XML-stroom te lezen. De methode retourneert
true
als de serializer-implementatie het beveiligingstoken kan deserialiseren op basis van het huidige element. In dit voorbeeld controleert deze methode of het huidige XML-element van de XML-lezer de juiste elementnaam en -naamruimte heeft. Als dit niet het geval is, wordt de basisklasse-implementatie van deze methode aangeroepen om het XML-element te verwerken.Overschrijf de ReadTokenCore(XmlReader, SecurityTokenResolver) methode. Met deze methode wordt de XML-inhoud van het beveiligingstoken gelezen en wordt de juiste in-memory weergave voor het token gemaakt. Als het XML-element waarop de doorgegeven XML-lezer zich bevindt niet herkent, wordt de implementatie van de basisklasse aanroepen om de door het systeem geleverde tokentypen te verwerken.
Overschrijf de CanWriteTokenCore(SecurityToken) methode. Deze methode retourneert
true
als deze de in-memory tokenweergave (doorgegeven als argument) kan converteren naar de XML-weergave. Als deze niet kan worden geconverteerd, wordt de implementatie van de basisklasse aanroepen.Overschrijf de WriteTokenCore(XmlWriter, SecurityToken) methode. Met deze methode wordt een beveiligingstokenweergave in het geheugen geconverteerd naar een XML-weergave. Als de methode niet kan worden geconverteerd, wordt de implementatie van de basisklasse aangeroepen.
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
Nadat u de vier vorige procedures hebt voltooid, integreert u het aangepaste beveiligingstoken met de beveiligingstokenprovider, verificator, manager en client- en servicereferenties.
Het aangepaste beveiligingstoken integreren met een beveiligingstokenprovider
De beveiligingstokenprovider maakt, wijzigt (indien nodig) en retourneert een exemplaar van het token. Als u een aangepaste provider wilt maken voor het aangepaste beveiligingstoken, maakt u een klasse die de klasse over neemt SecurityTokenProvider . In het volgende voorbeeld wordt de GetTokenCore methode overschreven om een exemplaar van de
CreditCardToken
. Zie How to: Create a Custom Security Token Provider (Een aangepaste beveiligingstokenprovider maken) voor meer informatie over aangepaste beveiligingstokenproviders.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
Het aangepaste beveiligingstoken integreren met een verificator voor beveiligingstokens
De beveiligingstoken-verificator valideert de inhoud van het beveiligingstoken wanneer het uit het bericht wordt geëxtraheerd. Als u een aangepaste verificator wilt maken voor het aangepaste beveiligingstoken, maakt u een klasse die wordt overgenomen van de SecurityTokenAuthenticator klasse. In het volgende voorbeeld wordt de ValidateTokenCore methode overschreven. Zie How to: Create a Custom Security Token Authenticator(Een aangepaste beveiligingstoken authenticator maken) voor meer informatie over aangepaste beveiligingstoken authenticators.
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
Het aangepaste beveiligingstoken integreren met een beveiligingstokenbeheer
De beveiligingstokenbeheerder maakt de juiste tokenprovider, beveiligingsautherator- en tokenserialisatieexemplaren. Als u een aangepast tokenbeheer wilt maken, maakt u een klasse die de klasse over neemt ClientCredentialsSecurityTokenManager . De primaire methoden van de klasse gebruiken een SecurityTokenRequirement om de juiste provider- en client- of servicereferenties te maken. Zie Overzicht: Aangepaste client- en servicereferenties maken voor meer informatie over aangepaste beveiligingstokenbeheerders.
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
Het aangepaste beveiligingstoken integreren met aangepaste client- en servicereferenties
De aangepaste client- en servicereferenties moeten worden toegevoegd om een API te bieden voor de toepassing, zodat aangepaste tokengegevens kunnen worden opgegeven die worden gebruikt door de infrastructuur voor aangepaste beveiligingstokens die eerder zijn gemaakt om de inhoud van het aangepaste beveiligingstoken op te geven en te verifiëren. In de volgende voorbeelden ziet u hoe dit kan worden gedaan. Zie Overzicht: Aangepaste client- en servicereferenties maken voor meer informatie over aangepaste client- en servicereferenties.
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
De aangepaste beveiligingstokenparametersklasse die u eerder hebt gemaakt, wordt gebruikt om het WCF-beveiligingsframework te laten weten dat een aangepast beveiligingstoken moet worden gebruikt bij de communicatie met een service. In de volgende procedure ziet u hoe u dit kunt doen.
Het aangepaste beveiligingstoken integreren met de binding
De klasse aangepaste beveiligingstokenparameters moet worden opgegeven in een van de tokenparametersverzamelingen die in de SecurityBindingElement klasse worden weergegeven. In het volgende voorbeeld wordt de verzameling gebruikt die wordt geretourneerd door
SignedEncrypted
. Met de code wordt het aangepaste token van de creditcard toegevoegd aan elk bericht dat van de client naar de service wordt verzonden, waarbij de inhoud automatisch is ondertekend en versleuteld.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
In dit onderwerp worden de verschillende codefragmenten weergegeven die nodig zijn om een aangepast token te implementeren en te gebruiken. Als u een volledig voorbeeld wilt zien van hoe al deze stukjes code bij elkaar passen, ziet u een aangepast token.
Zie ook
- SecurityToken
- SecurityTokenParameters
- WSSecurityTokenSerializer
- SecurityTokenProvider
- SecurityTokenAuthenticator
- IAuthorizationPolicy
- SecurityTokenRequirement
- SecurityTokenManager
- ClientCredentials
- ServiceCredentials
- SecurityBindingElement
- Overzicht: Aangepaste client- en servicereferenties maken
- Procedure: Een aangepaste beveiligingstoken authenticator maken
- Procedure: Een aangepaste beveiligingstokenprovider maken