Sdílet prostřednictvím


Zprostředkovatel tokenů zabezpečení SAML

Tato ukázka ukazuje, jak implementovat vlastního zprostředkovatele tokenu SAML klienta. Zprostředkovatel tokenu ve Windows Communication Foundation (WCF) slouží k poskytování přihlašovacích údajů infrastruktuře zabezpečení. Zprostředkovatel tokenu obecně zkoumá cíl a vydává příslušné přihlašovací údaje, aby infrastruktura zabezpečení zprávu zabezpečil. WCF se dodává s výchozím poskytovatelem tokenů Správce přihlašovacích údajů. WCF se také dodává se zprostředkovatelem tokenu CardSpace. Vlastní zprostředkovatelé tokenů jsou užitečné v následujících případech:

  • Pokud máte úložiště přihlašovacích údajů, se kterým tito poskytovatelé tokenů nemůžou pracovat.

  • Pokud chcete poskytnout vlastní mechanismus pro transformaci přihlašovacích údajů z bodu, když uživatel poskytne podrobnosti o tom, kdy klientská architektura WCF používá přihlašovací údaje.

  • Pokud vytváříte vlastní token.

Tato ukázka ukazuje, jak vytvořit vlastního zprostředkovatele tokenu, který umožňuje použití tokenu SAML získaného z rozhraní klienta WCF.

Tento příklad ukazuje následující souhrn:

  • Jak lze klienta nakonfigurovat s vlastním poskytovatelem tokenů.

  • Způsob předání tokenu SAML vlastním přihlašovacím údajům klienta

  • Způsob poskytnutí tokenu SAML klientskému rozhraní WCF

  • Způsob ověření serveru klientem pomocí certifikátu X.509 serveru.

Služba zveřejňuje dva koncové body pro komunikaci se službou definovanou pomocí konfiguračního souboru App.config. Každý koncový bod se skládá z adresy, vazby a kontraktu. Vazba se konfiguruje se standardním wsFederationHttpBindingzabezpečením zprávy. Jeden koncový bod očekává, že se klient ověří pomocí tokenu SAML, který používá symetrický ověřovací klíč, zatímco druhý očekává, že se klient ověří pomocí tokenu SAML, který používá asymetrický ověřovací klíč. Služba také nakonfiguruje certifikát služby pomocí serviceCredentials chování. Chování serviceCredentials umožňuje nakonfigurovat certifikát služby. Certifikát služby používá klient k ověření služby a poskytnutí ochrany zpráv. Následující konfigurace odkazuje na certifikát localhost nainstalovaný během ukázkové instalace, jak je popsáno v pokynech k instalaci na konci tohoto tématu. Toto serviceCredentials chování také umožňuje nakonfigurovat certifikáty, které jsou důvěryhodné pro podepisování tokenů SAML. Následující konfigurace odkazuje na certifikát Alice nainstalovaný během ukázky.

<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>

Následující kroky ukazují, jak vytvořit vlastního zprostředkovatele tokenu SAML a integrovat ho s WCF: architektura zabezpečení:

  1. Napište vlastního zprostředkovatele tokenu SAML.

    Ukázka implementuje vlastního zprostředkovatele tokenu SAML, který vrací token zabezpečení na základě kontrolního výrazu SAML, který je poskytován v době výstavby.

    K provedení této úlohy je vlastní zprostředkovatel tokenu odvozený z SecurityTokenProvider třídy a přepíše metodu GetTokenCore . Tato metoda vytvoří a vrátí novou 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);
    }
    
  2. Napište vlastního správce tokenů zabezpečení.

    Třída SecurityTokenManager se používá k vytvoření SecurityTokenProvider pro konkrétní SecurityTokenRequirement , který je předán v CreateSecurityTokenProvider metodě. Správce tokenů zabezpečení se také používá k vytvoření ověřovacích a serializačních tokenů tokenů, ale ty nejsou součástí této ukázky. V této ukázce vlastní správce tokenů zabezpečení dědí z ClientCredentialsSecurityTokenManager třídy a přepíše metodu CreateSecurityTokenProvider pro vrácení vlastního zprostředkovatele tokenu SAML, když předané požadavky na token indikují, že je token SAML požadován. Pokud třída přihlašovacích údajů klienta (viz krok 3) nezadá kontrolní výraz, správce tokenů zabezpečení vytvoří příslušnou instanci.

    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);
      }
    }
    
  3. Napište vlastní přihlašovací údaje klienta.

    Třída přihlašovacích údajů klienta slouží k reprezentaci přihlašovacích údajů nakonfigurovaných pro proxy klienta a vytvoří správce tokenů zabezpečení, který slouží k získání ověřovacích mechanismů tokenů, zprostředkovatelů tokenů a serializátoru tokenů.

    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);
     }
    }
    
  4. Nakonfigurujte klienta tak, aby používal vlastní přihlašovací údaje klienta.

    Ukázka odstraní výchozí třídu přihlašovacích údajů klienta a poskytuje novou třídu přihlašovacích údajů klienta, aby klient mohl použít vlastní přihlašovací údaje klienta.

    // 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);
    

Ve službě se zobrazí deklarace identity přidružené k volajícímu. Při spuštění ukázky se požadavky na operace a odpovědi zobrazí v okně konzoly klienta. Stisknutím klávesy ENTER v okně klienta klienta ukončete klienta.

Nastavení dávkového souboru

Dávkový soubor Setup.bat, který je součástí této ukázky, umožňuje nakonfigurovat server s příslušným certifikátem pro spuštění aplikace v místním prostředí, která vyžaduje zabezpečení založené na certifikátech serveru. Tento dávkový soubor musí být upraven tak, aby fungoval v počítačích nebo aby fungoval v případě, že není hostovaný.

Níže najdete stručný přehled různých částí dávkových souborů, aby je bylo možné upravit tak, aby běžely v příslušné konfiguraci.

  • Vytvoření certifikátu serveru:

    Následující řádky z dávkového souboru Setup.bat vytvoří certifikát serveru, který se má použít. Proměnná %SERVER_NAME% určuje název serveru. Změňte tuto proměnnou tak, aby byla zadána vlastní název serveru. Výchozí hodnota v tomto dávkovém souboru je localhost.

    Certifikát je uložený v úložišti My (Personal) pod umístěním úložiště LocalMachine.

    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
    
  • Instalace certifikátu serveru do důvěryhodného úložiště certifikátů klienta:

    Následující řádky v dávkovém souboru Setup.bat zkopírují certifikát serveru do úložiště důvěryhodných osob klienta. Tento krok je povinný, protože certifikáty generované Makecert.exe nejsou implicitně důvěryhodné klientským systémem. Pokud už máte certifikát, který je kořenový v kořenovém certifikátu klienta ( například certifikát vydaný Microsoftem), tento krok naplnění úložiště klientských certifikátů certifikátem pomocí certifikátu serveru se nevyžaduje.

    certmgr.exe -add -r LocalMachine -s My -c -n %SERVER_NAME% -r LocalMachine -s TrustedPeople
    
  • Vytvoření certifikátu vystavitele

    Následující řádky z dávkového souboru Setup.bat vytvoří certifikát vystavitele, který se má použít. Proměnná %USER_NAME% určuje název vystavitele. Změňte tuto proměnnou tak, aby určila vlastní název vystavitele. Výchozí hodnota v tomto dávkovém souboru je Alice.

    Certifikát je uložen v mém úložišti v umístění Úložiště 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
    
  • Instalace certifikátu vystavitele do úložiště důvěryhodných certifikátů serveru

    Následující řádky v dávkovém souboru Setup.bat zkopírují certifikát serveru do úložiště důvěryhodných osob klienta. Tento krok je povinný, protože certifikáty generované Makecert.exe nejsou implicitně důvěryhodné klientským systémem. Pokud už máte certifikát, který je kořenový v kořenovém certifikátu klienta ( například certifikát vydaný Microsoftem), tento krok naplnění úložiště certifikátů serveru certifikátem vystavitele se nevyžaduje.

    certmgr.exe -add -r CurrentUser -s My -c -n %USER_NAME% -r LocalMachine -s TrustedPeople
    

Nastavení a sestavení ukázky

  1. Ujistěte se, že jste pro ukázky windows Communication Foundation provedli jednorázovou instalační proceduru.

  2. Pokud chcete sestavit řešení, postupujte podle pokynů v části Sestavení ukázek Windows Communication Foundation.

Poznámka:

Pokud použijete Svcutil.exe k opětovnému vygenerování konfigurace pro tuto ukázku, nezapomeňte upravit název koncového bodu v konfiguraci klienta tak, aby odpovídal kódu klienta.

Spuštění ukázky na stejném počítači

  1. Spusťte Setup.bat z ukázkové instalační složky v příkazovém řádku sady Visual Studio s oprávněními správce. Tím se nainstalují všechny certifikáty potřebné pro spuštění ukázky.

    Poznámka:

    Dávkový soubor Setup.bat je navržený tak, aby běžel z příkazového řádku sady Visual Studio. Proměnná prostředí PATH nastavená v příkazovém řádku sady Visual Studio odkazuje na adresář, který obsahuje spustitelné soubory vyžadované skriptem Setup.bat.

  2. Spusťte Service.exe ze služby\bin.

  3. Spusťte Client.exe z \client\bin. Aktivita klienta se zobrazí v aplikaci konzoly klienta.

  4. Pokud klient a služba nemůžou komunikovat, přečtěte si téma Řešení potíží Tipy pro ukázky WCF.

Spuštění ukázky napříč počítači

  1. Vytvořte adresář na počítači služby pro binární soubory služby.

  2. Zkopírujte soubory programu služby do adresáře služby v počítači služby. Zkopírujte také soubory Setup.bat a Cleanup.bat do počítače služby.

  3. Musíte mít certifikát serveru s názvem subjektu, který obsahuje plně kvalifikovaný název domény počítače. Soubor Service.exe.config musí být aktualizován tak, aby odrážel tento nový název certifikátu. Certifikát serveru můžete vytvořit úpravou dávkového souboru Setup.bat. Všimněte si, že soubor setup.bat se musí spustit v okně Příkazového řádku pro vývojáře pro Visual Studio otevřené s oprávněními správce. Proměnnou %SERVER_NAME% musíte nastavit na plně kvalifikovaný název hostitele počítače, který se používá k hostování služby.

  4. Zkopírujte certifikát serveru do úložiště CurrentUser-Trusted Lidé klienta. Tento krok není nutný, pokud certifikát serveru vydá důvěryhodný vystavitel klienta.

  5. V souboru Service.exe.config v počítači služby změňte hodnotu základní adresy tak, aby místo localhost zadal plně kvalifikovaný název počítače.

  6. Na počítači služby spusťte Service.exe z příkazového řádku.

  7. Zkopírujte soubory klientského programu ze složky \client\bin\ ve složce specifické pro jazyk do klientského počítače.

  8. V souboru Client.exe.config na klientském počítači změňte hodnotu adresy koncového bodu tak, aby odpovídala nové adrese vaší služby.

  9. Na klientském počítači spusťte Client.exe okno příkazového řádku.

  10. Pokud klient a služba nemůžou komunikovat, přečtěte si téma Řešení potíží Tipy pro ukázky WCF.

Vyčištění po ukázce

  1. Po dokončení spuštění ukázky spusťte Cleanup.bat ve složce s ukázkami.