Dela via


Beständig tokenleverantör

Exemplet DurableIssuedTokenProvider visar hur du implementerar en anpassad tokenleverantör för klientutfärdade tokens.

Diskussion

En tokenprovider i Windows Communication Foundation (WCF) används för att ange 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 en CardSpace-tokenprovider. Anpassade tokenprovidrar är användbara i följande fall:

  • Om du har ett arkiv för autentiseringsuppgifter som den inbyggda tokenprovidern inte kan använda.

  • Om du vill ange en egen anpassad mekanism för att omvandla autentiseringsuppgifterna från den tidpunkt då användaren anger informationen till när WCF-klienten använder autentiseringsuppgifterna.

  • Om du skapar en anpassad token.

Det här exemplet visar hur du skapar en anpassad tokenprovider som cachelagrar token som utfärdats av en säkerhetstokentjänst (STS).

Sammanfattningsvis visar det här exemplet följande:

  • Hur en klient kan konfigureras med en anpassad tokenprovider.

  • Hur utfärdade token kan cachelagras och tillhandahållas till WCF-klienten.

  • Hur servern autentiseras av klienten med hjälp av serverns X.509-certifikat.

Det här exemplet består av ett klientkonsolprogram (Client.exe), ett tjänstkonsolprogram för säkerhetstoken (Securitytokenservice.exe) och ett tjänstkonsolprogram (Service.exe). Tjänsten implementerar ett kontrakt som definierar ett kommunikationsmönster för begäran-svar. Kontraktet definieras av ICalculator gränssnittet, som exponerar matematiska åtgärder (lägg till, subtrahera, multiplicera och dividera). Klienten hämtar en säkerhetstoken från Security Token Service (STS) och gör synkrona begäranden till tjänsten för en viss matematisk åtgärd och tjänsten svarar med resultatet. Klientaktiviteten visas i konsolfönstret.

Anmärkning

Konfigurationsproceduren och bygginstruktionerna för det här exemplet finns i slutet av det här avsnittet.

Det här exemplet exponerar ICalculator-kontraktet med < wsHttpBinding>. Konfigurationen av den här bindningen på klienten visas i följande kod.

<bindings>
  <wsFederationHttpBinding>
    <binding name="ServiceFed">
      <security mode="Message">
        <message issuedKeyType="SymmetricKey"
                 issuedTokenType="http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV1.1">
          <issuer address="http://localhost:8000/sts/windows"
                  binding="wsHttpBinding" />
        </message>
      </security>
    </binding>
  </wsFederationHttpBinding>
</bindings>

På elementet security av wsFederationHttpBinding konfigurerar värdet i mode vilket säkerhetsläge som ska användas. I det här exemplet används säkerhet för meddelanden, vilket är anledningen till att elementet messagewsFederationHttpBinding anges i elementet securitywsFederationHttpBinding. Elementet issuer av wsFederationHttpBinding inuti elementet message av wsFederationHttpBinding anger adressen och bindningen för säkerhetstokentjänsten som utfärdar en säkerhetstoken till klienten, så att klienten kan autentisera sig mot kalkylatortjänsten.

Konfigurationen av den här bindningen för tjänsten visas i följande kod.

<bindings>
  <wsFederationHttpBinding>
    <binding name="ServiceFed">
      <security mode="Message">
        <message issuedKeyType="SymmetricKey"
                 issuedTokenType="http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV1.1">
          <issuerMetadata address="http://localhost:8000/sts/mex">
            <identity>
              <certificateReference storeLocation="CurrentUser"
                                    storeName="TrustedPeople"
                                    x509FindType="FindBySubjectDistinguishedName"
                                    findValue="CN=STS" />
            </identity>
          </issuerMetadata>
        </message>
      </security>
    </binding>
  </wsFederationHttpBinding>
</bindings>

På elementet security av wsFederationHttpBinding konfigurerar värdet i mode vilket säkerhetsläge som ska användas. I det här exemplet används säkerhet för meddelanden, vilket är anledningen till att elementet messagewsFederationHttpBinding anges i elementet securitywsFederationHttpBinding. Elementet issuerMetadata i wsFederationHttpBinding inuti elementet message i wsFederationHttpBinding anger adressen och identiteten för en slutpunkt som kan användas för att hämta metadata för säkerhetstokentjänsten.

Beteendet för tjänsten visas i följande kod.

<behavior name="ServiceBehavior">
  <serviceDebug includeExceptionDetailInFaults="true" />
  <serviceMetadata httpGetEnabled="true" />
  <serviceCredentials>
    <issuedTokenAuthentication>
      <knownCertificates>
        <add storeLocation="LocalMachine"
              storeName="TrustedPeople"
              x509FindType="FindBySubjectDistinguishedName"
              findValue="CN=STS" />
      </knownCertificates>
    </issuedTokenAuthentication>
    <serviceCertificate storeLocation="LocalMachine"
                        storeName="My"
                        x509FindType="FindBySubjectDistinguishedName"
                        findValue="CN=localhost" />
  </serviceCredentials>
</behavior>

Elementet issuedTokenAuthentication i elementet serviceCredentials gör att tjänsten kan ange begränsningar för de token som klienterna kan presentera under autentiseringen. Den här konfigurationen anger att token som signerats av ett certifikat vars ämnesnamn är CN=STS godkänns av tjänsten.

Security Token Service exponerar en enskild slutpunkt med hjälp av standarden wsHttpBinding. Säkerhetstokentjänsten svarar på begäran från klienter om token och, förutsatt att klienten autentiserar med ett Windows-konto, utfärdar en token som innehåller klientens användarnamn som ett anspråk i den utfärdade token. Som en del av att skapa token signerar Security Token Service token med hjälp av den privata nyckeln som är associerad med CN=STS-certifikatet. Dessutom skapar den en symmetrisk nyckel och krypterar den med hjälp av den offentliga nyckeln som är associerad med CN=localhost-certifikatet. När token returneras till klienten returnerar Security Token Service även den symmetriska nyckeln. Klienten presenterar den utfärdade token för kalkylatortjänsten och bevisar att den känner till den symmetriska nyckeln genom att signera meddelandet med den nyckeln.

Anpassade klientautentiseringsuppgifter och tokenprovider

Följande steg visar hur du utvecklar en anpassad tokenprovider som cachelagrar utfärdade token och integrerar den med WCF: säkerhet.

Så här utvecklar du en anpassad tokenprovider

  1. Skriv en anpassad tokenprovider.

    Exemplet implementerar en anpassad tokenprovider som returnerar en säkerhetstoken som hämtats från en cache.

    För att utföra den här uppgiften härleder den anpassade tokenprovidern SecurityTokenProvider klassen och åsidosätter GetTokenCore metoden. Den här metoden försöker hämta en token från cachen, eller om det inte går att hitta en token i cacheminnet hämtar en token från den underliggande providern och cachelagrar sedan token. I båda fallen returnerar metoden en SecurityToken.

    protected override SecurityToken GetTokenCore(TimeSpan timeout)
    {
      GenericXmlSecurityToken token;
      if (!this.cache.TryGetToken(target, issuer, out token))
      {
        token = (GenericXmlSecurityToken) this.innerTokenProvider.GetToken(timeout);
        this.cache.AddToken(token, target, issuer);
      }
      return token;
    }
    
  2. Skriv anpassad säkerhetstokenhanterare.

    En SecurityTokenManager används för att skapa en SecurityTokenProvider för en specifik SecurityTokenRequirement som skickas till den i CreateSecurityTokenProvider metoden. Säkerhetstokenhanteraren 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ätter CreateSecurityTokenProvider metoden för att returnera den anpassade tokenprovidern när kraven för godkänd token anger att en utfärdad token begärs.

    class DurableIssuedTokenClientCredentialsTokenManager :
     ClientCredentialsSecurityTokenManager
    {
      IssuedTokenCache cache;
    
      public DurableIssuedTokenClientCredentialsTokenManager ( DurableIssuedTokenClientCredentials creds ): base(creds)
      {
        this.cache = creds.IssuedTokenCache;
      }
    
      public override SecurityTokenProvider CreateSecurityTokenProvider ( SecurityTokenRequirement tokenRequirement )
      {
        if (IsIssuedSecurityTokenRequirement(tokenRequirement))
        {
          return new DurableIssuedSecurityTokenProvider ((IssuedSecurityTokenProvider)base.CreateSecurityTokenProvider( tokenRequirement), this.cache);
        }
        else
        {
          return base.CreateSecurityTokenProvider(tokenRequirement);
        }
      }
    }
    
  3. Skriv en anpassad klientautentiseringsuppgift.

    En klass för klientautentiseringsuppgifter används för att representera de autentiseringsuppgifter som har konfigurerats för klientproxyn och skapar säkerhetstokenhanteraren som används för att hämta tokenautentisering, tokenprovidrar och token-serialiserare.

    public class DurableIssuedTokenClientCredentials : ClientCredentials
    {
      IssuedTokenCache cache;
    
      public DurableIssuedTokenClientCredentials() : base()
      {
      }
    
      DurableIssuedTokenClientCredentials ( DurableIssuedTokenClientCredentials other) : base(other)
      {
        this.cache = other.cache;
      }
    
      public IssuedTokenCache IssuedTokenCache
      {
        get
        {
          return this.cache;
        }
        set
        {
          this.cache = value;
        }
      }
    
      protected override ClientCredentials CloneCore()
      {
        return new DurableIssuedTokenClientCredentials(this);
      }
    
      public override SecurityTokenManager CreateSecurityTokenManager()
      {
        return new DurableIssuedTokenClientCredentialsTokenManager ((DurableIssuedTokenClientCredentials)this.Clone());
      }
    }
    
  4. Implementera tokencachen. Exempelimplementeringen använder en abstrakt basklass genom vilken konsumenter av en viss tokencache interagerar med cachen.

    public abstract class IssuedTokenCache
    {
      public abstract void AddToken ( GenericXmlSecurityToken token, EndpointAddress target, EndpointAddress issuer);
      public abstract bool TryGetToken(EndpointAddress target, EndpointAddress issuer, out GenericXmlSecurityToken cachedToken);
    }
    // Configure the client to use the custom client credential.
    

    För att klienten ska kunna använda den anpassade klientautentiseringsuppgiften tar exemplet bort standardklassen för klientautentiseringsuppgifter och tillhandahåller den nya klassen för klientautentiseringsuppgifter.

    clientFactory.Endpoint.Behaviors.Remove<ClientCredentials>();
    DurableIssuedTokenClientCredentials durableCreds = new DurableIssuedTokenClientCredentials();
    durableCreds.IssuedTokenCache = cache;
    durableCreds.ServiceCertificate.Authentication.CertificateValidationMode = X509CertificateValidationMode.PeerOrChainTrust;
    clientFactory.Endpoint.Behaviors.Add(durableCreds);
    

Genomföra exemplet

Se följande instruktioner för att köra exemplet. När du kör exemplet visas begäran om säkerhetstoken i konsolfönstret för säkerhetstokentjänsten. Åtgärdsbegäranden och svar visas i klient- och tjänstkonsolens fönster. Tryck på RETUR i något av konsolfönstren för att stänga av programmet.

Batch-Setup.cmd-filen

Med Setup.cmd batchfil som ingår i det här exemplet kan du konfigurera server- och säkerhetstokentjänsten med relevanta certifikat för att köra ett program med egen värd. Batchfilen skapar två certifikat både i certifikatarkivet CurrentUser/TrustedPeople. Det första certifikatet har ämnesnamnet CN=STS och används av Security Token Service för att signera de säkerhetstoken som det utfärdar till klienten. Det andra certifikatet har ämnesnamnet CN=localhost och används av Security Token Service för att kryptera en hemlighet så att tjänsten kan dekryptera den.

Så här konfigurerar du, skapar och kör exemplet

  1. Kör filen Setup.cmd för att skapa de certifikat som krävs.

  2. Skapa lösningen genom att följa anvisningarna i Skapa Windows Communication Foundation-exempel. Se till att alla projekt i lösningen har skapats (Delad, RSTRSTR, Tjänst, SecurityTokenService och Klient).

  3. Kontrollera att både Service.exe och SecurityTokenService.exe körs med administratörsbehörighet.

  4. Kör Client.exe.

Att städa upp efter provet

Kör Cleanup.cmd i exempelmappen när du har kört exemplet.