SAML-tokenprovider
Det här exemplet visar hur du implementerar en saml-tokenprovider för anpassad klient. En tokenprovider i Windows Communication Foundation (WCF) används för att tillhandahålla autentiseringsuppgifter till säkerhetsinfrastrukturen. Tokenprovidern undersöker i allmänhet målet och utfärdar lämpliga autentiseringsuppgifter så att säkerhetsinfrastrukturen kan skydda meddelandet. WCF levereras med standardprovidern för Credential Manager-token. WCF levereras också med en CardSpace-tokenprovider. Anpassade tokenprovidrar är användbara i följande fall:
Om du har ett arkiv för autentiseringsuppgifter som dessa tokenprovidrar inte kan använda.
Om du vill ange en egen anpassad mekanism för att omvandla autentiseringsuppgifterna från den tidpunkt då användaren tillhandahåller informationen till när WCF-klientramverket använder autentiseringsuppgifterna.
Om du skapar en anpassad token.
Det här exemplet visar hur du skapar en anpassad tokenprovider som gör att en SAML-token som hämtas utanför WCF-klientramverket kan användas.
Sammanfattningsvis visar det här exemplet följande:
Hur en klient kan konfigureras med en anpassad tokenprovider.
Hur en SAML-token kan skickas till autentiseringsuppgifterna för den anpassade klienten.
Så här tillhandahålls SAML-token till WCF-klientramverket.
Hur servern autentiseras av klienten med hjälp av serverns X.509-certifikat.
Tjänsten exponerar två slutpunkter för kommunikation med tjänsten, som definieras med hjälp av konfigurationsfilen App.config. Varje slutpunkt består av en adress, en bindning och ett kontrakt. Bindningen konfigureras med en standard wsFederationHttpBinding
, som använder Meddelandesäkerhet. En slutpunkt förväntar sig att klienten autentiserar med en SAML-token som använder en symmetrisk bevisnyckel medan den andra förväntar sig att klienten autentiserar med en SAML-token som använder en asymmetrisk bevisnyckel. Tjänsten konfigurerar även tjänstcertifikatet med hjälp av serviceCredentials
beteende. Med serviceCredentials
beteendet kan du konfigurera ett tjänstcertifikat. Ett tjänstcertifikat används av en klient för att autentisera tjänsten och tillhandahålla meddelandeskydd. Följande konfiguration refererar till det "localhost"-certifikat som installerades under exempelkonfigurationen enligt beskrivningen i installationsanvisningarna i slutet av det här avsnittet. Med serviceCredentials
beteendet kan du också konfigurera certifikat som är betrodda för att signera SAML-token. Följande konfiguration refererar till alicecertifikatet som installerades under exemplet.
<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>
Följande steg visar hur du utvecklar en anpassad SAML-tokenprovider och integrerar den med WCF: security framework:
Skriv en anpassad SAML-tokenprovider.
Exemplet implementerar en anpassad SAML-tokenprovider som returnerar en säkerhetstoken baserat på en SAML-försäkran som tillhandahålls vid byggtiden.
För att utföra den här uppgiften härleds den anpassade tokenprovidern SecurityTokenProvider från klassen och åsidosätter GetTokenCore metoden. Den här metoden skapar och returnerar en ny
SecurityToken
.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); }
Skriv anpassad säkerhetstokenhanterare.
Klassen SecurityTokenManager används för att skapa SecurityTokenProvider för specifika SecurityTokenRequirement som skickas till den i
CreateSecurityTokenProvider
-metoden. En säkerhetstokenhanterare används också för att skapa tokenautentisering och token-serialiserare, men de omfattas inte av det här exemplet. I det här exemplet ärver den anpassade säkerhetstokenhanteraren från ClientCredentialsSecurityTokenManager klassen och åsidosätterCreateSecurityTokenProvider
metoden för att returnera den anpassade SAML-tokenprovidern när kraven för godkänd token anger att SAML-token begärs. Om klassen för klientautentiseringsuppgifter (se steg 3) inte har angett något intyg skapar säkerhetstokenhanteraren en lämplig instans.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); } }
Skriv en anpassad klientautentiseringsuppgift.
Klassen klientautentiseringsuppgifter används för att representera de autentiseringsuppgifter som har konfigurerats för klientproxyn och skapar en säkerhetstokenhanterare som används för att hämta tokenautentisering, tokenprovidrar och token-serialiserare.
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); } }
Konfigurera klienten så att den använder den anpassade klientautentiseringsuppgiften.
Exemplet tar bort standardklassen för klientautentiseringsuppgifter och tillhandahåller den nya klientens autentiseringsklass så att klienten kan använda den anpassade klientautentiseringsuppgiften.
// 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);
I tjänsten visas de anspråk som är associerade med anroparen. När du kör exemplet visas åtgärdsbegäranden och svar i klientkonsolfönstret. Tryck på RETUR i klientfönstret för att stänga av klienten.
Konfigurera Batch-fil
Med Setup.bat batchfil som ingår i det här exemplet kan du konfigurera servern med relevant certifikat för att köra ett program med egen värd som kräver servercertifikatbaserad säkerhet. Den här batchfilen måste ändras för att fungera mellan datorer eller för att fungera i ett fall som inte är värdbaserat.
Följande ger en kort översikt över de olika avsnitten i batchfilerna så att de kan ändras så att de körs i lämplig konfiguration.
Skapa servercertifikatet:
Följande rader från Setup.bat batchfil skapar det servercertifikat som ska användas. Variabeln
%SERVER_NAME%
anger servernamnet. Ändra den här variabeln för att ange ditt eget servernamn. Standardvärdet i den här batchfilen är localhost.Certifikatet lagras i mitt (personligt) arkiv under platsen för LocalMachine-arkivet.
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
Installera servercertifikatet i klientens betrodda certifikatarkiv:
Följande rader i Setup.bat batchfil kopierar servercertifikatet till klientarkivet för betrodda personer. Det här steget krävs eftersom certifikat som genereras av Makecert.exe inte är implicit betrodda av klientsystemet. Om du redan har ett certifikat som är rotat i ett klientbetrott rotcertifikat, till exempel ett Microsoft-utfärdat certifikat, krävs inte det här steget för att fylla i klientcertifikatarkivet med servercertifikatet.
certmgr.exe -add -r LocalMachine -s My -c -n %SERVER_NAME% -r LocalMachine -s TrustedPeople
Skapa utfärdarcertifikatet.
Följande rader från Setup.bat batchfil skapar utfärdarcertifikatet som ska användas. Variabeln
%USER_NAME%
anger utfärdarnamnet. Ändra den här variabeln om du vill ange ett eget utfärdarnamn. Standardvärdet i den här batchfilen är Alice.Certifikatet lagras i Mitt arkiv under lagringsplatsen CurrentUser.
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
Installera utfärdarcertifikatet i serverns betrodda certifikatarkiv.
Följande rader i Setup.bat batchfil kopierar servercertifikatet till klientarkivet för betrodda personer. Det här steget krävs eftersom certifikat som genereras av Makecert.exe inte är implicit betrodda av klientsystemet. Om du redan har ett certifikat som är rotat i ett betrott rotcertifikat för klienten, till exempel ett Microsoft-utfärdat certifikat, krävs inte det här steget för att fylla i servercertifikatarkivet med utfärdarcertifikatet.
certmgr.exe -add -r CurrentUser -s My -c -n %USER_NAME% -r LocalMachine -s TrustedPeople
Så här konfigurerar och skapar du exemplet
Kontrollera att du har utfört engångsinstallationsproceduren för Windows Communication Foundation-exempel.
Skapa lösningen genom att följa anvisningarna i Skapa Windows Communication Foundation-exempel.
Kommentar
Om du använder Svcutil.exe för att återskapa konfigurationen för det här exemplet måste du ändra slutpunktsnamnet i klientkonfigurationen så att det matchar klientkoden.
Så här kör du exemplet på samma dator
Kör Setup.bat från exempelinstallationsmappen i en Visual Studio-kommandotolk som körs med administratörsbehörighet. Detta installerar alla certifikat som krävs för att köra exemplet.
Kommentar
Den Setup.bat batchfilen är utformad för att köras från en Visual Studio-kommandotolk. Variabeln PATH-miljö som angetts i Visual Studio-kommandotolken pekar på katalogen som innehåller körbara filer som krävs av Setup.bat skriptet.
Starta Service.exe från service\bin.
Starta Client.exe från \client\bin. Klientaktiviteten visas i klientkonsolprogrammet.
Om klienten och tjänsten inte kan kommunicera kan du läsa Felsökningstips för WCF-exempel.
Så här kör du exemplet mellan datorer
Skapa en katalog på tjänstdatorn för tjänstens binärfiler.
Kopiera tjänstprogramfilerna till tjänstkatalogen på tjänstdatorn. Kopiera även Setup.bat- och Cleanup.bat-filerna till tjänstdatorn.
Du måste ha ett servercertifikat med ämnesnamnet som innehåller datorns fullständigt kvalificerade domännamn. Filen Service.exe.config måste uppdateras för att återspegla det nya certifikatnamnet. Du kan skapa servercertifikat genom att ändra Setup.bat batchfil. Observera att den setup.bat filen måste köras i en kommandotolk för utvecklare för Visual Studio öppnas med administratörsbehörighet. Du måste ange variabeln
%SERVER_NAME%
till det fullständigt kvalificerade värdnamnet för den dator som används som värd för tjänsten.Kopiera servercertifikatet till CurrentUser-Trusted Personer-arkivet för klienten. Det här steget är inte nödvändigt när servercertifikatet utfärdas av en betrodd klientutfärdare.
I filen Service.exe.config på tjänstdatorn ändrar du värdet för basadressen för att ange ett fullständigt kvalificerat datornamn i stället för localhost.
På tjänstdatorn kör du Service.exe från en kommandotolk.
Kopiera klientprogramfilerna från mappen \client\bin\ under den språkspecifika mappen till klientdatorn.
I filen Client.exe.config på klientdatorn ändrar du slutpunktens adressvärde så att det matchar tjänstens nya adress.
Starta från ett kommandotolksfönster på klientdatorn
Client.exe
.Om klienten och tjänsten inte kan kommunicera kan du läsa Felsökningstips för WCF-exempel.
Rensa efter exemplet
- Kör Cleanup.bat i exempelmappen när du har kört exemplet.