Partilhar via


Provedor de token emitido durável

O exemplo DurableIssuedTokenProvider demonstra como implementar um provedor de token emitido pelo cliente personalizado.

Debate

Um provedor de token no Windows Communication Foundation (WCF) é usado para fornecer credenciais para a infraestrutura de segurança. O provedor de token em geral examina o destino e emite credenciais apropriadas para que a infraestrutura de segurança possa proteger a mensagem. O WCF é fornecido com um provedor de token CardSpace. Os provedores de token personalizados são úteis nos seguintes casos:

  • Se você tiver um armazenamento de credenciais com o qual o provedor de token interno não possa operar.

  • Se você quiser fornecer seu próprio mecanismo personalizado para transformar as credenciais do ponto em que o usuário fornece os detalhes até quando o cliente WCF usa as credenciais.

  • Se você estiver criando um token personalizado.

Este exemplo mostra como criar um provedor de token personalizado que armazena em cache tokens emitidos por um STS (Serviço de Token de Segurança).

Para resumir, este exemplo demonstra o seguinte:

  • Como um cliente pode ser configurado com um provedor de token personalizado.

  • Como os tokens emitidos podem ser armazenados em cache e fornecidos ao cliente WCF.

  • Como o servidor é autenticado pelo cliente usando o certificado X.509 do servidor.

Este exemplo consiste em um programa de console cliente (Client.exe), um programa de console de serviço de token de segurança (Securitytokenservice.exe) e um programa de console de serviço (Service.exe). O serviço implementa um contrato que define um padrão de comunicação solicitação-resposta. O contrato é definido pela ICalculator interface, que expõe operações matemáticas (adicionar, subtrair, multiplicar e dividir). O cliente obtém um token de segurança do Serviço de Token de Segurança (STS) e faz solicitações síncronas ao serviço para uma determinada operação matemática e o serviço responde com o resultado. A atividade do cliente é visível na janela do console.

Nota

O procedimento de configuração e as instruções de compilação para este exemplo estão localizados no final deste tópico.

Este exemplo expõe o contrato ICalculator usando o wsHttpBinding>.< A configuração dessa ligação no cliente é mostrada no código a seguir.

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

security No elemento de , o mode valor configura qual modo de wsFederationHttpBindingsegurança deve ser usado. Neste exemplo, a segurança de mensagens está sendo usada, e é por isso que o message elemento de wsFederationHttpBinding é especificado dentro do security elemento de wsFederationHttpBinding. O issuer elemento de dentro message do elemento de especifica o endereço e a associação para o Serviço de Token de wsFederationHttpBinding Segurança que emite um token de wsFederationHttpBinding segurança para o cliente para que o cliente possa se autenticar no serviço de Calculadora.

A configuração dessa ligação no serviço é mostrada no código a seguir.

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

security No elemento de , o mode valor configura qual modo de wsFederationHttpBindingsegurança deve ser usado. Neste exemplo, a segurança de mensagens está sendo usada, e é por isso que o message elemento de wsFederationHttpBinding é especificado dentro do security elemento de wsFederationHttpBinding. O issuerMetadata elemento de dentro message do elemento de especifica o endereço e a identidade de um ponto de extremidade que pode ser usado para recuperar metadados para o Serviço de Token de wsFederationHttpBindingwsFederationHttpBinding Segurança.

O comportamento para o serviço é mostrado no código a seguir.

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

O issuedTokenAuthentication elemento dentro do serviceCredentials elemento permite que o serviço especifique restrições nos tokens que permite que os clientes apresentem durante a autenticação. Essa configuração especifica que os tokens assinados por um certificado cujo Nome da Entidade é CN=STS são aceitos pelo serviço.

O Serviço de Token de Segurança expõe um único ponto de extremidade usando o padrão wsHttpBinding. O Serviço de Token de Segurança responde à solicitação de tokens de clientes e, desde que o cliente se autentique usando uma conta do Windows, emite um token que contém o nome de usuário do cliente como uma declaração no token emitido. Como parte da criação do token, o Serviço de Token de Segurança assina o token usando a chave privada associada ao certificado CN=STS. Além disso, ele cria uma chave simétrica e a criptografa usando a chave pública associada ao certificado CN=localhost. Ao retornar o token para o cliente, o Serviço de Token de Segurança também retorna a chave simétrica. O cliente apresenta o token emitido ao serviço Calculadora e prova que conhece a chave simétrica assinando a mensagem com essa chave.

Credenciais de cliente personalizadas e provedor de token

As etapas a seguir mostram como desenvolver um provedor de token personalizado que armazena tokens emitidos em cache e o integra ao WCF: security.

Para desenvolver um provedor de token personalizado

  1. Escreva um provedor de token personalizado.

    O exemplo implementa um provedor de token personalizado que retorna um token de segurança recuperado de um cache.

    Para executar essa tarefa, o provedor de token personalizado deriva a SecurityTokenProvider classe e substitui o GetTokenCore método. Esse método tenta obter um token do cache ou, se um token não puder ser encontrado no cache, recupera um token do provedor subjacente e, em seguida, armazena esse token em cache. Em ambos os casos, o método retorna um SecurityTokenarquivo .

    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. Escreva um gerenciador de token de segurança personalizado.

    O SecurityTokenManager é usado para criar um SecurityTokenProvider para um específico SecurityTokenRequirement que é passado para ele no CreateSecurityTokenProvider método. O gerenciador de tokens de segurança também é usado para criar autenticadores de token e serializadores de token, mas esses não são cobertos por este exemplo. Neste exemplo, o gerenciador de token de segurança personalizado herda da ClientCredentialsSecurityTokenManager classe e substitui o CreateSecurityTokenProvider método para retornar o provedor de token personalizado quando os requisitos de token passados indicam que um token emitido é solicitado.

    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. Escreva uma credencial de cliente personalizada.

    Uma classe de credenciais de cliente é usada para representar as credenciais configuradas para o proxy do cliente e cria o gerenciador de token de segurança que é usado para obter autenticadores de token, provedores de token e serializadores de token.

    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. Implemente o cache de token. A implementação de exemplo usa uma classe base abstrata através da qual os consumidores de um determinado cache de token interagem com o cache.

    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.
    

    Para o cliente usar a credencial de cliente personalizada, o exemplo exclui a classe de credencial de cliente padrão e fornece a nova classe de credencial de cliente.

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

Executar o exemplo

Consulte as instruções a seguir para executar o exemplo. Quando você executa o exemplo, a solicitação para o token de segurança é mostrada na janela do console do Serviço de Token de Segurança. As solicitações e respostas de operação são exibidas nas janelas do cliente e do console de serviço. Pressione ENTER em qualquer uma das janelas do console para desligar o aplicativo.

O arquivo em lote Setup.cmd

O arquivo em lote Setup.cmd incluído neste exemplo permite configurar o servidor e o serviço de token de segurança com certificados relevantes para executar um aplicativo auto-hospedado. O arquivo em lotes cria dois certificados no armazenamento de certificados CurrentUser/TrustedPeople. O primeiro certificado tem um nome de assunto CN=STS e é usado pelo Serviço de Token de Segurança para assinar os tokens de segurança que ele emite para o cliente. O segundo certificado tem um nome de assunto CN=localhost e é usado pelo Serviço de Token de Segurança para criptografar um segredo para que o serviço possa descriptografá-lo.

Para configurar, compilar e executar o exemplo

  1. Execute o arquivo Setup.cmd para criar os certificados necessários.

  2. Para criar a solução, siga as instruções em Criando os exemplos do Windows Communication Foundation. Certifique-se de que todos os projetos na solução sejam criados (Shared, RSTRSTR, Service, SecurityTokenService e Client).

  3. Certifique-se de que Service.exe e SecurityTokenService.exe estejam sendo executados com privilégios de administrador.

  4. Execute Client.exe.

Para limpar após a amostra

Execute Cleanup.cmd na pasta de exemplos depois de terminar de executar o exemplo.