Poznámka:
Přístup k této stránce vyžaduje autorizaci. Můžete se zkusit přihlásit nebo změnit adresáře.
Přístup k této stránce vyžaduje autorizaci. Můžete zkusit změnit adresáře.
Toto téma ukazuje, jak vytvořit vlastní token zabezpečení pomocí SecurityToken třídy a jak ho integrovat s vlastním poskytovatelem tokenů zabezpečení a ověřovacím objektem. Kompletní příklad kódu najdete v ukázce vlastního tokenu .
Token zabezpečení je v podstatě element XML, který je používán rozhraním zabezpečení WCF (Windows Communication Foundation) k reprezentaci deklarací identity o odesílateli uvnitř zprávy SOAP. Zabezpečení WCF poskytuje různé tokeny pro režimy ověřování poskytované systémem. Mezi příklady patří token zabezpečení certifikátu X.509 reprezentovaný třídou X509SecurityToken nebo token zabezpečení uživatelského jména reprezentovaný třídou UserNameSecurityToken.
V některých případech se zadanými typy nepodporuje režim ověřování nebo přihlašovací údaje. V takovém případě je nutné vytvořit vlastní token zabezpečení pro poskytnutí xml reprezentace vlastních přihlašovacích údajů uvnitř zprávy SOAP.
Následující postupy ukazují, jak vytvořit vlastní token zabezpečení a jak ho integrovat s infrastrukturou zabezpečení WCF. Toto téma vytvoří token platební karty, který slouží k předávání informací o platební kartě klienta na server.
Další informace o vlastních přihlašovacích údaji a správci tokenů zabezpečení naleznete v tématu Návod: Vytvoření vlastních přihlašovacích údajů klienta a služby.
V oboru názvů System.IdentityModel.Tokens najdete další třídy, které představují tokeny zabezpečení.
Procedures
Klientská aplikace musí být poskytována způsobem, jak zadat informace o platební kartě pro infrastrukturu zabezpečení. Tyto informace jsou pro aplikaci zpřístupněny vlastní třídou přihlašovacích údajů klienta. Prvním krokem je vytvoření třídy, která bude představovat informace o platební kartě pro vlastní přihlašovací údaje klienta.
Vytvoření třídy, která představuje informace o platební kartě uvnitř přihlašovacích údajů klienta
Definujte novou třídu, která představuje informace o platební kartě pro aplikaci. Následující příklad pojmenuje třídu
CreditCardInfo.Přidejte do třídy odpovídající vlastnosti, aby aplikace nastavila potřebné informace pro vlastní token. V tomto příkladu má třída tři vlastnosti:
CardNumber,CardIssueraExpirationDate.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
Dále musí být vytvořena třída, která představuje vlastní token zabezpečení. Třídu využívají zprostředkovatel tokenů zabezpečení, ověřovatelé a serializátoři pro výměnu informací o tokenu zabezpečení v rámci bezpečnostní infrastruktury WCF.
Vytvoření vlastní třídy tokenu zabezpečení
Definujte novou třídu odvozenou z třídy SecurityToken. Tento příklad vytvoří třídu s názvem
CreditCardToken.Přepište vlastnost Id. Tato vlastnost slouží k získání místního identifikátoru tokenu zabezpečení, který slouží k nasměrování na reprezentaci XML tokenu zabezpečení z jiných prvků uvnitř zprávy SOAP. V tomto příkladu může být identifikátor tokenu předán buď jako parametr konstruktoru, nebo se vygeneruje nový náhodný identifikátor při každém vytvoření instance tokenu zabezpečení.
Implementujte vlastnost SecurityKeys. Tato vlastnost vrátí kolekci klíčů zabezpečení, které instance tokenu zabezpečení představuje. Tyto klíče může WCF použít k podepisování nebo šifrování částí zprávy SOAP. V tomto příkladu token zabezpečení platební karty nesmí obsahovat žádné klíče zabezpečení; proto implementace vždy vrátí prázdnou kolekci.
Přepište vlastnosti ValidFrom a ValidTo. Tyto vlastnosti služba WCF používá k určení platnosti instance tokenu zabezpečení. V tomto příkladu má token zabezpečení platební karty pouze datum vypršení platnosti, takže
ValidFromvlastnost vrátí DateTime hodnotu, která představuje datum a čas vytvoření 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
Při vytvoření nového typu tokenu zabezpečení vyžaduje implementaci SecurityTokenParameters třídy. Implementace se používá v konfiguraci elementu vazby zabezpečení k reprezentaci nového typu tokenu. Třída parametrů tokenu zabezpečení slouží jako šablona, která se používá ke shodě se skutečnou instancí tokenu zabezpečení při zpracování zprávy. Šablona poskytuje další vlastnosti, které může aplikace použít k určení kritérií, jimž musí token zabezpečení vyhovovat, aby mohl být použit nebo ověřen. Následující příklad nepřidá žádné další vlastnosti, takže pouze typ tokenu zabezpečení se shoduje, když infrastruktura WCF hledá instanci tokenu zabezpečení, která se má použít nebo ověřit.
Vytvoření vlastní třídy parametrů tokenu zabezpečení
Definujte novou třídu odvozenou z třídy SecurityTokenParameters.
Implementujte metodu CloneCore . Zkopírujte všechna interní pole definovaná ve třídě( pokud existuje). Tento příklad nedefinuje žádná další pole.
Implementujte vlastnost pouze pro čtení SupportsClientAuthentication. Tato vlastnost vrátí
true, pokud typ tokenu zabezpečení reprezentovaný touto třídou lze použít k ověření klienta ve službě. V tomto příkladu lze token zabezpečení platební karty použít k ověření klienta ve službě.Implementujte vlastnost pouze pro čtení SupportsServerAuthentication. Tato vlastnost vrátí
true, pokud lze typ tokenu zabezpečení reprezentovaný touto třídou použít k ověření služby u klienta. V tomto příkladu se token zabezpečení platební karty nedá použít k ověření služby klientovi.Implementujte vlastnost pouze pro čtení SupportsClientWindowsIdentity. Tato vlastnost vrátí
true, pokud typ tokenu zabezpečení reprezentovaný touto třídou lze mapovat na účet Systému Windows. Pokud ano, výsledek ověřování je reprezentován WindowsIdentity instancí třídy. V tomto příkladu nelze token namapovat na účet systému Windows.Implementujte metodu CreateKeyIdentifierClause(SecurityToken, SecurityTokenReferenceStyle) . Tato metoda je volána architekturou zabezpečení WCF, pokud vyžaduje odkaz na instanci tokenu zabezpečení reprezentované touto třídou parametrů tokenu zabezpečení. Obě instance bezpečnostního tokenu i SecurityTokenReferenceStyle, který určuje typ požadovaného odkazu, se této metodě předají jako argumenty. V tomto příkladu jsou tokenem zabezpečení platební karty podporovány pouze interní odkazy. Třída SecurityToken má funkce pro vytváření interních odkazů, proto implementace nevyžaduje další kód.
Implementujte metodu InitializeSecurityTokenRequirement(SecurityTokenRequirement) . Metoda je volána WCF pro převod instance třídy parametrů zabezpečovacího tokenu na instanci třídy SecurityTokenRequirement. Výsledek používají zprostředkovatelé tokenů zabezpečení k vytvoření příslušné instance tokenu zabezpečení.
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
Tokeny zabezpečení se přenášejí uvnitř zpráv PROTOKOLU SOAP, které vyžadují mechanismus překladu mezi reprezentací tokenu zabezpečení v paměti a reprezentací on-the-wire. WCF k provedení této úlohy používá serializátor tokenu zabezpečení. Každý vlastní bezpečnostní token musí být doprovázen vlastním serializátorem bezpečnostních tokenů, který může serializovat a deserializovat vlastní bezpečnostní token ze zprávy SOAP.
Poznámka:
Odvozené klíče jsou ve výchozím nastavení povolené. Pokud vytvoříte vlastní token zabezpečení a použijete ho jako primární token, WCF z něj odvozuje klíč. Během toho volá vlastní serializátor tokenu zabezpečení, aby zapsal SecurityKeyIdentifierClause pro vlastní token zabezpečení při serializaci DerivedKeyToken do sítě. Na straně přijímajícího, při deserializaci tokenu ze sítě, DerivedKeyToken serializátor očekává SecurityTokenReference prvek jako hlavní podřízený prvek. Pokud serializátor vlastního bezpečnostního tokenu nepřidal prvek SecurityTokenReference při serializaci jeho typu klauzule, je vyvolána výjimka.
Vytvoření vlastního serializátoru tokenu zabezpečení
Definujte novou třídu odvozenou z třídy WSSecurityTokenSerializer.
Přepište metodu CanReadTokenCore(XmlReader), která využívá XmlReader k čtení XML datového proudu. Metoda vrátí
true, pokud implementace serializátoru může deserializovat token zabezpečení na základě jeho aktuálního prvku. V tomto příkladu tato metoda zkontroluje, zda aktuální element XML čtenáře XML má správný název elementu a obor názvů. Pokud se tak nestane, zavolá implementaci metody základní třídy k zpracování XML elementu.Překryjte metodu ReadTokenCore(XmlReader, SecurityTokenResolver). Tato metoda načte obsah XML tokenu zabezpečení a vytvoří odpovídající reprezentaci v paměti. Pokud nerozpozná XML element, na kterém se nachází předaná čtečka XML, volá implementaci základní třídy pro zpracování systémem poskytovaných typů tokenů.
Překryjte metodu CanWriteTokenCore(SecurityToken). Tato metoda vrátí
true, pokud může převést reprezentaci tokenu v paměti (předáno jako argument) na reprezentaci XML. Pokud nelze převést, zavolá implementaci základní třídy.Překryjte metodu WriteTokenCore(XmlWriter, SecurityToken). Tato metoda převede reprezentaci tokenu zabezpečení v paměti na reprezentaci XML. Pokud metoda nemůže převést, volá implementaci základní třídy.
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
Po dokončení čtyř předchozích postupů propojte vlastní bezpečnostní token se zprostředkovatelem bezpečnostních tokenů, ověřovacím objektem, správcem a přihlašovacími údaji klienta a služby.
Integrace vlastního tokenu zabezpečení se zprostředkovatelem tokenu zabezpečení
Zprostředkovatel tokenu zabezpečení vytvoří, v případě potřeby upraví a vrátí instanci tokenu. Pokud chcete vytvořit vlastního zprostředkovatele pro vlastní token zabezpečení, vytvořte třídu, která dědí z SecurityTokenProvider třídy. Následující příklad přepíše metodu GetTokenCore pro vrácení instance
CreditCardToken. Další informace o vlastních poskytovateli tokenů zabezpečení naleznete v tématu Postupy: Vytvoření vlastního zprostředkovatele tokenů zabezpečení.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
Integrace vlastního tokenu zabezpečení s ověřovačem tokenu zabezpečení
Ověřovací token zabezpečení ověří obsah tokenu zabezpečení při extrahování ze zprávy. Pokud chcete vytvořit vlastní ověřovací objekt pro vlastní token zabezpečení, vytvořte třídu, která dědí z SecurityTokenAuthenticator třídy. Následující příklad přepíše metodu ValidateTokenCore . Další informace o vlastních ověřovacích tokenech zabezpečení naleznete v tématu Postupy: Vytvoření vlastního ověřovacího tokenu zabezpečení.
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 Classpublic 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
Integrace vlastního tokenu zabezpečení se správcem tokenů zabezpečení
Správce bezpečnostních tokenů vytvoří příslušného poskytovatele tokenů, autentizátor zabezpečení a instance serializátoru tokenů. Pokud chcete vytvořit vlastního správce tokenů, vytvořte třídu, která dědí z ClientCredentialsSecurityTokenManager třídy. Primární metody třídy používají SecurityTokenRequirement k vytvoření příslušného zprostředkovatele a přihlašovacích údajů klienta nebo služby. Další informace o vlastních správcích tokenů zabezpečení naleznete v tématu Návod: Vytvoření vlastních přihlašovacích údajů klienta a služby.
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 Classpublic 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
Integrace vlastního tokenu zabezpečení s vlastními přihlašovacími údaji klienta a služby
Vlastní přihlašovací údaje klienta a služby musí být přidány, aby bylo možné aplikaci poskytnout rozhraní API, aby bylo možné zadat vlastní informace o tokenech, které používá infrastruktura vlastních tokenů zabezpečení vytvořená dříve k poskytování a ověřování obsahu vlastního tokenu zabezpečení. Následující ukázky ukazují, jak to lze provést. Další informace o vlastních přihlašovacích údaji klienta a služby najdete v tématu Návod: Vytvoření vlastních přihlašovacích údajů klienta a služby.
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 Classpublic 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
Třída parametrů vlastního tokenu zabezpečení vytvořená dříve slouží k informování architektury zabezpečení WCF, že se při komunikaci se službou musí použít vlastní token zabezpečení. Následující postup ukazuje, jak to lze provést.
Integrace vlastního tokenu zabezpečení s vazbou
Vlastní třída parametrů tokenu zabezpečení musí být zadána v jedné z kolekcí parametrů tokenu, které jsou vystaveny ve SecurityBindingElement třídě. Následující příklad používá kolekci vrácenou
SignedEncrypted. Kód přidá vlastní token platební karty ke každé zprávě odeslané z klienta do služby s jejím obsahem automaticky podepsaným a zašifrovaným.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
Toto téma ukazuje různé části kódu potřebné k implementaci a použití vlastního tokenu. Kompletní příklad toho, jak se všechny tyto části kódu slouží dohromady, najdete v Custom Token.
Viz také
- SecurityToken
- SecurityTokenParameters
- WSSecurityTokenSerializer
- SecurityTokenProvider
- SecurityTokenAuthenticator
- IAuthorizationPolicy
- SecurityTokenRequirement
- SecurityTokenManager
- ClientCredentials
- ServiceCredentials
- SecurityBindingElement
- Návod: Vytvoření vlastních přihlašovacích údajů klienta a služby
- Postupy: Vytvoření vlastního ověřovače tokenu zabezpečení
- Postupy: Vytvoření vlastního zprostředkovatele tokenů zabezpečení