SAML-tokenprovider
In dit voorbeeld ziet u hoe u een aangepaste SAML-tokenprovider voor clients implementeert. Een tokenprovider in WcF (Windows Communication Foundation) wordt gebruikt voor het opgeven van referenties aan de beveiligingsinfrastructuur. De tokenprovider in het algemeen onderzoekt het doel en problemen met de juiste referenties, zodat de beveiligingsinfrastructuur het bericht kan beveiligen. WCF wordt geleverd met de standaard Credential Manager-tokenprovider. WCF wordt ook geleverd met een CardSpace-tokenprovider. Aangepaste tokenproviders zijn handig in de volgende gevallen:
Als u een referentiearchief hebt waarmee deze tokenproviders niet kunnen werken.
Als u uw eigen aangepaste mechanisme wilt opgeven voor het transformeren van de referenties vanaf het moment waarop de gebruiker de details verstrekt wanneer het WCF-clientframework de referenties gebruikt.
Als u een aangepast token bouwt.
In dit voorbeeld ziet u hoe u een aangepaste tokenprovider bouwt waarmee een SAML-token dat is verkregen van buiten het WCF-clientframework kan worden gebruikt.
Samenvattend ziet u in dit voorbeeld het volgende:
Hoe een client kan worden geconfigureerd met een aangepaste tokenprovider.
Hoe een SAML-token kan worden doorgegeven aan de aangepaste clientreferenties.
Hoe het SAML-token wordt geleverd aan het WCF-clientframework.
Hoe de server wordt geverifieerd door de client met behulp van het X.509-certificaat van de server.
De service maakt twee eindpunten beschikbaar voor communicatie met de service, gedefinieerd met behulp van het configuratiebestand App.config. Elk eindpunt bestaat uit een adres, een binding en een contract. De binding wordt geconfigureerd met een standaard wsFederationHttpBinding
, die gebruikmaakt van berichtbeveiliging. Het ene eindpunt verwacht dat de client wordt geverifieerd met een SAML-token dat gebruikmaakt van een symmetrische proof-sleutel terwijl de andere verwacht dat de client wordt geverifieerd met een SAML-token dat gebruikmaakt van een asymmetrische proof-sleutel. De service configureert ook het servicecertificaat met behulp van serviceCredentials
gedrag. Met het serviceCredentials
gedrag kunt u een servicecertificaat configureren. Een servicecertificaat wordt door een client gebruikt om de service te verifiëren en berichtbeveiliging te bieden. De volgende configuratie verwijst naar het localhost-certificaat dat tijdens de voorbeeldinstallatie is geïnstalleerd, zoals beschreven in de installatie-instructies aan het einde van dit onderwerp. Met het serviceCredentials
gedrag kunt u ook certificaten configureren die worden vertrouwd om SAML-tokens te ondertekenen. De volgende configuratie verwijst naar het 'Alice'-certificaat dat tijdens het voorbeeld is geïnstalleerd.
<system.serviceModel>
<services>
<service
name="Microsoft.ServiceModel.Samples.CalculatorService"
behaviorConfiguration="CalculatorServiceBehavior">
<host>
<baseAddresses>
<!-- configure base address provided by host -->
<add
baseAddress="http://localhost:8000/servicemodelsamples/service/" />
</baseAddresses>
</host>
<!-- use base address provided by host -->
<!-- Endpoint that expect SAML tokens with Symmetric proof keys -->
<endpoint address="calc/symm"
binding="wsFederationHttpBinding"
bindingConfiguration="Binding1"
contract="Microsoft.ServiceModel.Samples.ICalculator" />
<!-- Endpoint that expect SAML tokens with Asymmetric proof keys -->
<endpoint address="calc/asymm"
binding="wsFederationHttpBinding"
bindingConfiguration="Binding2"
contract="Microsoft.ServiceModel.Samples.ICalculator" />
</service>
</services>
<bindings>
<wsFederationHttpBinding>
<!-- Binding that expect SAML tokens with Symmetric proof keys -->
<binding name="Binding1">
<security mode="Message">
<message negotiateServiceCredential ="false"
issuedKeyType="SymmetricKey"
issuedTokenType="http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV1.1" />
</security>
</binding>
<!-- Binding that expect SAML tokens with Asymmetric proof keys -->
<binding name="Binding2">
<security mode="Message">
<message negotiateServiceCredential ="false"
issuedKeyType="AsymmetricKey"
issuedTokenType="http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV1.1" />
</security>
</binding>
</wsFederationHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="CalculatorServiceBehavior">
<!--
The serviceCredentials behavior allows one to define a service certificate.
A service certificate is used by a client to authenticate the service and provide message protection.
This configuration references the "localhost" certificate installed during the setup instructions.
-->
<serviceCredentials>
<!-- Set allowUntrustedRsaIssuers to true to allow self-signed, asymmetric key based SAML tokens -->
<issuedTokenAuthentication allowUntrustedRsaIssuers ="true" >
<!-- Add Alice to the list of certs trusted to issue SAML tokens -->
<knownCertificates>
<add storeLocation="LocalMachine"
storeName="TrustedPeople"
x509FindType="FindBySubjectName"
findValue="Alice"/>
</knownCertificates>
</issuedTokenAuthentication>
<serviceCertificate storeLocation="LocalMachine"
storeName="My"
x509FindType="FindBySubjectName"
findValue="localhost" />
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
De volgende stappen laten zien hoe u een aangepaste SAML-tokenprovider ontwikkelt en integreert met WCF: beveiligingsframework:
Schrijf een aangepaste SAML-tokenprovider.
In het voorbeeld wordt een aangepaste SAML-tokenprovider geïmplementeerd die een beveiligingstoken retourneert op basis van een SAML-assertie die tijdens de bouw wordt geleverd.
Om deze taak uit te voeren, wordt de aangepaste tokenprovider afgeleid van de SecurityTokenProvider klasse en wordt de GetTokenCore methode overschreven. Met deze methode wordt een nieuwe
SecurityToken
methode gemaakt en geretourneerd.protected override SecurityToken GetTokenCore(TimeSpan timeout) { // Create a SamlSecurityToken from the provided assertion SamlSecurityToken samlToken = new SamlSecurityToken(assertion); // Create a SecurityTokenSerializer that will be used to // serialize the SamlSecurityToken WSSecurityTokenSerializer ser = new WSSecurityTokenSerializer(); // Create a memory stream to write the serialized token into // Use an initial size of 64Kb MemoryStream s = new MemoryStream(UInt16.MaxValue); // Create an XmlWriter over the stream XmlWriter xw = XmlWriter.Create(s); // Write the SamlSecurityToken into the stream ser.WriteToken(xw, samlToken); // Seek back to the beginning of the stream s.Seek(0, SeekOrigin.Begin); // Load the serialized token into a DOM XmlDocument dom = new XmlDocument(); dom.Load(s); // Create a KeyIdentifierClause for the SamlSecurityToken SamlAssertionKeyIdentifierClause samlKeyIdentifierClause = samlToken.CreateKeyIdentifierClause<SamlAssertionKeyIdentifierClause>(); // Return a GenericXmlToken from the XML for the // SamlSecurityToken, the proof token, the valid from and valid // until times from the assertion and the key identifier clause // created above return new GenericXmlSecurityToken(dom.DocumentElement, proofToken, assertion.Conditions.NotBefore, assertion.Conditions.NotOnOrAfter, samlKeyIdentifierClause, samlKeyIdentifierClause, null); }
Schrijf aangepaste beveiligingstokenbeheer.
De SecurityTokenManager klasse wordt gebruikt om te maken SecurityTokenProvider voor specifieke SecurityTokenRequirement gegevens die eraan worden doorgegeven in
CreateSecurityTokenProvider
de methode. Een beveiligingstokenbeheer wordt ook gebruikt om tokenauthenialators en tokenserialisatie te maken, maar die vallen niet onder dit voorbeeld. In dit voorbeeld neemt de aangepaste beveiligingstokenbeheer de klasse over ClientCredentialsSecurityTokenManager en overschrijft deCreateSecurityTokenProvider
methode om de aangepaste SAML-tokenprovider te retourneren wanneer de doorgegeven tokenvereisten aangeven dat het SAML-token wordt aangevraagd. Als de clientreferentieklasse (zie stap 3) geen assertie heeft opgegeven, maakt de beveiligingstokenbeheerder een geschikt exemplaar.public class SamlSecurityTokenManager : ClientCredentialsSecurityTokenManager { SamlClientCredentials samlClientCredentials; public SamlSecurityTokenManager ( SamlClientCredentials samlClientCredentials) : base(samlClientCredentials) { // Store the creating client credentials this.samlClientCredentials = samlClientCredentials; } public override SecurityTokenProvider CreateSecurityTokenProvider ( SecurityTokenRequirement tokenRequirement ) { // If token requirement matches SAML token return the // custom SAML token provider if (tokenRequirement.TokenType == SecurityTokenTypes.Saml || tokenRequirement.TokenType == "http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV1.1") { // Retrieve the SAML assertion and proof token from the // client credentials SamlAssertion assertion = this.samlClientCredentials.Assertion; SecurityToken prooftoken = this.samlClientCredentials.ProofToken; // If either the assertion of proof token is null... if (assertion == null || prooftoken == null) { // ...get the SecurityBindingElement and then the // specified algorithm suite SecurityBindingElement sbe = null; SecurityAlgorithmSuite sas = null; if ( tokenRequirement.TryGetProperty<SecurityBindingElement> ( "http://schemas.microsoft.com/ws/2006/05/servicemodel/securitytokenrequirement/SecurityBindingElement", out sbe)) { sas = sbe.DefaultAlgorithmSuite; } // If the token requirement is for a SymmetricKey based token.. if (tokenRequirement.KeyType == SecurityKeyType.SymmetricKey) { // Create a symmetric proof token prooftoken = SamlUtilities.CreateSymmetricProofToken ( tokenRequirement.KeySize ); // and a corresponding assertion based on the claims specified in the client credentials assertion = SamlUtilities.CreateSymmetricKeyBasedAssertion ( this.samlClientCredentials.Claims, new X509SecurityToken ( samlClientCredentials.ClientCertificate.Certificate ), new X509SecurityToken ( samlClientCredentials.ServiceCertificate.DefaultCertificate ), (BinarySecretSecurityToken)prooftoken, sas); } // otherwise... else { // Create an asymmetric proof token prooftoken = SamlUtilities.CreateAsymmetricProofToken(); // and a corresponding assertion based on the claims // specified in the client credentials assertion = SamlUtilities.CreateAsymmetricKeyBasedAssertion ( this.samlClientCredentials.Claims, prooftoken, sas ); } } // Create a SamlSecurityTokenProvider based on the assertion and proof token return new SamlSecurityTokenProvider(assertion, prooftoken); } // otherwise use base implementation else { return base.CreateSecurityTokenProvider(tokenRequirement); } }
Schrijf een aangepaste clientreferentie.
De klasse clientreferenties wordt gebruikt om de referenties te vertegenwoordigen die zijn geconfigureerd voor de clientproxy en maakt een beveiligingstokenbeheer dat wordt gebruikt voor het verkrijgen van token authenticators, tokenproviders en token serializer.
public class SamlClientCredentials : ClientCredentials { ClaimSet claims; SamlAssertion assertion; SecurityToken proofToken; public SamlClientCredentials() : base() { // Set SupportInteractive to false to suppress Cardspace UI base.SupportInteractive = false; } protected SamlClientCredentials(SamlClientCredentials other) : base ( other ) { // Just do reference copy given sample nature this.assertion = other.assertion; this.claims = other.claims; this.proofToken = other.proofToken; } public SamlAssertion Assertion { get { return assertion; } set { assertion = value; } } public SecurityToken ProofToken { get { return proofToken; } set { proofToken = value; } } public ClaimSet Claims { get { return claims; } set { claims = value; } } protected override ClientCredentials CloneCore() { return new SamlClientCredentials(this); } public override SecurityTokenManager CreateSecurityTokenManager() { // return custom security token manager return new SamlSecurityTokenManager(this); } }
Configureer de client voor het gebruik van de aangepaste clientreferenties.
In het voorbeeld wordt de standaardreferentieklasse van de client verwijderd en wordt de nieuwe clientreferentieklasse geleverd, zodat de client de aangepaste clientreferenties kan gebruiken.
// Create new credentials class SamlClientCredentials samlCC = new SamlClientCredentials(); // Set the client certificate. This is the cert that will be used to sign the SAML token in the symmetric proof key case samlCC.ClientCertificate.SetCertificate(StoreLocation.CurrentUser, StoreName.My, X509FindType.FindBySubjectName, "Alice"); // Set the service certificate. This is the cert that will be used to encrypt the proof key in the symmetric proof key case samlCC.ServiceCertificate.SetDefaultCertificate(StoreLocation.CurrentUser, StoreName.TrustedPeople, X509FindType.FindBySubjectName, "localhost"); // Create some claims to put in the SAML assertion IList<Claim> claims = new List<Claim>(); claims.Add(Claim.CreateNameClaim(samlCC.ClientCertificate.Certificate.Subject)); ClaimSet claimset = new DefaultClaimSet(claims); samlCC.Claims = claimset; // set new credentials client.ChannelFactory.Endpoint.Behaviors.Remove(typeof(ClientCredentials)); client.ChannelFactory.Endpoint.Behaviors.Add(samlCC);
Op de service worden de claims weergegeven die zijn gekoppeld aan de aanroeper. Wanneer u het voorbeeld uitvoert, worden de bewerkingsaanvragen en -antwoorden weergegeven in het clientconsolevenster. Druk op Enter in het clientvenster om de client af te sluiten.
Batch-bestand instellen
Met het Setup.bat batchbestand dat in dit voorbeeld is opgenomen, kunt u de server configureren met het relevante certificaat om een zelf-hostende toepassing uit te voeren waarvoor beveiliging op basis van servercertificaten is vereist. Dit batchbestand moet worden gewijzigd om te kunnen werken op computers of om te kunnen werken in een niet-gehost geval.
Hieronder vindt u een kort overzicht van de verschillende secties van de batchbestanden, zodat ze kunnen worden gewijzigd om te worden uitgevoerd in de juiste configuratie.
Het servercertificaat maken:
De volgende regels uit het Setup.bat batchbestand maken het servercertificaat dat moet worden gebruikt. De
%SERVER_NAME%
variabele geeft de servernaam op. Wijzig deze variabele om uw eigen servernaam op te geven. De standaardwaarde in dit batchbestand is localhost.Het certificaat wordt opgeslagen in Mijn (Persoonlijk) archief onder de locatie van het LocalMachine-archief.
echo ************ echo Server cert setup starting echo %SERVER_NAME% echo ************ echo making server cert echo ************ makecert.exe -sr LocalMachine -ss My -a sha1 -n CN=%SERVER_NAME% -sky exchange -pe
Het servercertificaat installeren in het vertrouwde certificaatarchief van de client:
Met de volgende regels in het Setup.bat batchbestand kopieert u het servercertificaat naar het archief vertrouwde personen van de client. Deze stap is vereist omdat certificaten die worden gegenereerd door Makecert.exe niet impliciet worden vertrouwd door het clientsysteem. Als u al een certificaat hebt dat is geroot in een vertrouwd basiscertificaat van een client, bijvoorbeeld een door Microsoft uitgegeven certificaat, is deze stap voor het invullen van het clientcertificaatarchief met het servercertificaat niet vereist.
certmgr.exe -add -r LocalMachine -s My -c -n %SERVER_NAME% -r LocalMachine -s TrustedPeople
Het certificaat van de uitgever maken.
Met de volgende regels uit het Setup.bat batchbestand maakt u het certificaat van de uitgever dat moet worden gebruikt. De
%USER_NAME%
variabele geeft de naam van de verlener op. Wijzig deze variabele om de naam van uw eigen verlener op te geven. De standaardwaarde in dit batchbestand is Alice.Het certificaat wordt opgeslagen in Mijn archief onder de locatie van het CurrentUser-archief.
echo ************ echo Server cert setup starting echo %SERVER_NAME% echo ************ echo making server cert echo ************ makecert.exe -sr CurrentUser -ss My -a sha1 -n CN=%USER_NAME% -sky exchange -pe
Het certificaat van de uitgever installeren in het vertrouwde certificaatarchief van de server.
Met de volgende regels in het Setup.bat batchbestand kopieert u het servercertificaat naar het archief vertrouwde personen van de client. Deze stap is vereist omdat certificaten die worden gegenereerd door Makecert.exe niet impliciet worden vertrouwd door het clientsysteem. Als u al een certificaat hebt dat is geroot in een vertrouwd basiscertificaat van een client, bijvoorbeeld een door Microsoft uitgegeven certificaat, is deze stap van het vullen van het servercertificaatarchief met het certificaat van de uitgever niet vereist.
certmgr.exe -add -r CurrentUser -s My -c -n %USER_NAME% -r LocalMachine -s TrustedPeople
Het voorbeeld instellen en bouwen
Zorg ervoor dat u de eenmalige installatieprocedure voor de Windows Communication Foundation-voorbeelden hebt uitgevoerd.
Volg de instructies in Het bouwen van de Windows Communication Foundation-voorbeelden om de oplossing te bouwen.
Notitie
Als u Svcutil.exe gebruikt om de configuratie voor dit voorbeeld opnieuw te genereren, moet u de naam van het eindpunt in de clientconfiguratie wijzigen zodat deze overeenkomt met de clientcode.
Het voorbeeld uitvoeren op dezelfde computer
Voer Setup.bat uit vanuit de voorbeeldinstallatiemap in een Visual Studio-opdrachtprompt die wordt uitgevoerd met beheerdersbevoegdheden. Hiermee worden alle certificaten geïnstalleerd die vereist zijn voor het uitvoeren van het voorbeeld.
Notitie
Het Setup.bat batchbestand is ontworpen om te worden uitgevoerd vanaf een Visual Studio-opdrachtprompt. De omgevingsvariabele PATH die in de Visual Studio-opdrachtprompt is ingesteld, verwijst naar de map met uitvoerbare bestanden die zijn vereist voor het Setup.bat script.
Start Service.exe vanuit service\bin.
Start Client.exe vanuit \client\bin. Clientactiviteit wordt weergegeven in de clientconsoletoepassing.
Als de client en service niet kunnen communiceren, raadpleegt u Tips voor probleemoplossing voor WCF-voorbeelden.
Het voorbeeld uitvoeren op computers
Maak een map op de servicecomputer voor de binaire servicebestanden.
Kopieer de serviceprogrammabestanden naar de servicemap op de servicecomputer. Kopieer ook de Setup.bat- en Cleanup.bat-bestanden naar de servicecomputer.
U moet een servercertificaat hebben met de onderwerpnaam die de volledig gekwalificeerde domeinnaam van de computer bevat. Het bestand Service.exe.config moet worden bijgewerkt om deze nieuwe certificaatnaam weer te geven. U kunt een servercertificaat maken door het Setup.bat batchbestand te wijzigen. Houd er rekening mee dat het setup.bat-bestand moet worden uitgevoerd in een opdrachtprompt voor ontwikkelaars voor Visual Studio-venster dat is geopend met beheerdersbevoegdheden. U moet de
%SERVER_NAME%
variabele instellen op de volledig gekwalificeerde hostnaam van de computer die wordt gebruikt om de service te hosten.Kopieer het servercertificaat naar het archief CurrentUser-Trusted Mensen van de client. Deze stap is niet nodig wanneer het servercertificaat wordt uitgegeven door een vertrouwde verlener van een client.
Wijzig in het bestand Service.exe.config op de servicecomputer de waarde van het basisadres om een volledig gekwalificeerde computernaam op te geven in plaats van localhost.
Voer op de servicecomputer Service.exe uit vanaf een opdrachtprompt.
Kopieer de clientprogrammabestanden uit de map \client\bin\ onder de taalspecifieke map naar de clientcomputer.
Wijzig in het bestand Client.exe.config op de clientcomputer de adreswaarde van het eindpunt zodat deze overeenkomt met het nieuwe adres van uw service.
Start
Client.exe
op de clientcomputer vanaf een opdrachtpromptvenster.Als de client en service niet kunnen communiceren, raadpleegt u Tips voor probleemoplossing voor WCF-voorbeelden.
Opschonen na het voorbeeld
- Voer Cleanup.bat uit in de map met voorbeelden zodra u klaar bent met het uitvoeren van het voorbeeld.