Compartir a través de


Proveedor duradero de tokens emitidos

El ejemplo DurableIssuedTokenProvider muestra cómo implementar un proveedor de tokens emitido por un cliente personalizado.

Discusión

Un proveedor de tokens de Windows Communication Foundation (WCF) se usa para proporcionar credenciales a la infraestructura de seguridad. El proveedor de tokens en general examina el destino y emite las credenciales adecuadas para que la infraestructura de seguridad pueda proteger el mensaje. WCF se incluye con un proveedor de tokens de CardSpace. Los proveedores de tokens personalizados son útiles en los casos siguientes:

  • Si tiene un almacén de credenciales con el que el proveedor de tokens integrado no puede funcionar.

  • Si desea proporcionar su propio mecanismo personalizado para transformar las credenciales desde el punto en que el usuario proporciona los detalles a cuando el cliente WCF usa las credenciales.

  • Si está creando un token personalizado.

En este ejemplo se muestra cómo crear un proveedor de tokens personalizado que almacena en caché los tokens emitidos por un servicio de token de seguridad (STS).

En resumen, este ejemplo muestra lo siguiente:

  • Cómo se puede configurar un cliente con un proveedor de tokens personalizado.

  • Cómo se pueden almacenar en caché los tokens emitidos y proporcionarse al cliente WCF.

  • Cómo el cliente autentica al servidor utilizando el certificado X.509 del servidor.

Este ejemplo consta de un programa de consola de cliente (Client.exe), un programa de consola de servicio de token de seguridad (Securitytokenservice.exe) y un programa de consola de servicio (Service.exe). El servicio implementa un contrato que define un patrón de comunicación de solicitud-respuesta. El contrato se define mediante la ICalculator interfaz , que expone las operaciones matemáticas (agregar, restar, multiplicar y dividir). El cliente obtiene un token de seguridad del servicio de token de seguridad (STS) y realiza solicitudes sincrónicas al servicio para una operación matemática determinada y el servicio responde con el resultado. La actividad del cliente está visible en la ventana de la consola.

Nota:

El procedimiento de configuración y las instrucciones de compilación de este ejemplo se encuentran al final de este tema.

En este ejemplo se expone el contrato ICalculator mediante <wsHttpBinding>. La configuración de este enlace en el cliente se muestra en el código siguiente.

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

En el elemento security de wsFederationHttpBinding, el valor mode configura el modo de seguridad que se debe usar. En este ejemplo, se usa la seguridad de los mensajes, por lo que el message elemento de wsFederationHttpBinding se especifica dentro del security elemento de wsFederationHttpBinding. El elemento issuer de wsFederationHttpBinding que se encuentra dentro del elemento message de wsFederationHttpBinding especifica la dirección y el enlace para el Servicio de token de seguridad que emite un token de seguridad para el cliente, de manera que el cliente pueda autenticarlo con el servicio de calculadora.

La configuración de este enlace en el servicio se muestra en el código siguiente.

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

En el elemento security de wsFederationHttpBinding, el valor mode configura el modo de seguridad que se debe usar. En este ejemplo, se usa la seguridad de los mensajes, por lo que el message elemento de wsFederationHttpBinding se especifica dentro del security elemento de wsFederationHttpBinding. El elemento issuerMetadata de wsFederationHttpBinding dentro del elemento message de wsFederationHttpBinding especifica la dirección y la identidad de un punto de conexión que se puede usar para recuperar metadatos para el Servicio de Token de Seguridad.

El comportamiento del servicio se muestra en el código siguiente.

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

El issuedTokenAuthentication elemento dentro del serviceCredentials elemento permite al servicio especificar restricciones en los tokens que permite a los clientes presentar durante la autenticación. Esta configuración especifica que el servicio acepta los tokens firmados por un certificado cuyo nombre de firmante es CN=STS.

El Servicio de token de seguridad expone un solo punto de conexión con el wsHttpBinding estándar. El servicio de token de seguridad responde a la solicitud de los clientes para los tokens y, siempre que el cliente se autentique mediante una cuenta de Windows, emite un token que contiene el nombre de usuario del cliente como una notificación en el token emitido. Como parte de la creación del token, el servicio de token de seguridad firma el token mediante la clave privada asociada al certificado CN=STS. Además, crea una clave simétrica y la cifra mediante la clave pública asociada al certificado CN=localhost. Al devolver el token al cliente, el servicio de token de seguridad también devuelve la clave simétrica. El cliente presenta el token emitido al servicio Calculator y demuestra que conoce la clave simétrica firmando el mensaje con esa clave.

Credenciales de cliente personalizadas y proveedor de tokens

En los pasos siguientes se muestra cómo desarrollar un proveedor de tokens personalizado que almacena en caché los tokens emitidos e integrarlo con WCF: seguridad.

Para desarrollar un proveedor de tokens personalizado

  1. Escriba un proveedor de tokens personalizado.

    El ejemplo implementa un proveedor de tokens personalizado que devuelve un token de seguridad recuperado de una memoria caché.

    Para realizar esta tarea, el proveedor de tokens personalizado deriva la SecurityTokenProvider clase e invalida el GetTokenCore método . Este método intenta obtener un token de la memoria caché, o si no se encuentra un token en la memoria caché, recupera un token del proveedor subyacente y, a continuación, almacena en caché ese token. En ambos casos, el método devuelve un 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. Redacte un administrador de tokens de seguridad personalizado.

    SecurityTokenManager se utiliza para crear un SecurityTokenProvider para un SecurityTokenRequirement específico que se le pasa en el método CreateSecurityTokenProvider. El administrador de tokens de seguridad también se usa para crear autenticadores de tokens y serializadores de tokens, pero estos no están cubiertos por este ejemplo. En este ejemplo, el administrador de tokens de seguridad personalizado hereda de la clase ClientCredentialsSecurityTokenManager e invalida el método CreateSecurityTokenProvider para devolver el proveedor de tokens personalizado cuando los requisitos de tokens pasados indican que se solicita un token emitido.

    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. Escriba una credencial de cliente personalizada.

    Se usa una clase de credenciales de cliente para representar las credenciales configuradas para el proxy de cliente y crea el administrador de tokens de seguridad que se usa para obtener autenticadores de tokens, proveedores de tokens y serializadores de tokens.

    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 el almacenamiento en caché de tokens. La implementación de ejemplo usa una clase base abstracta a través de la cual los consumidores de una caché de tokens determinada interactúan con la memoria caché.

    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 que el cliente use la credencial de cliente personalizada, el ejemplo elimina la clase de credenciales de cliente predeterminada y proporciona la nueva clase de credenciales 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);
    

Ejecución del ejemplo

Consulte las instrucciones siguientes para ejecutar el ejemplo. Al ejecutar el ejemplo, la solicitud del token de seguridad se muestra en la ventana de la consola del servicio de token de seguridad. Las solicitudes y respuestas de la operación se muestran en las ventanas de consola de cliente y servicio. Presione ENTRAR en cualquiera de las ventanas de consola para apagar la aplicación.

Archivo por lotes Setup.cmd

El Setup.cmd archivo por lotes incluido con este ejemplo permite configurar el servidor y el servicio de token de seguridad con certificados pertinentes para ejecutar una aplicación autohospedada. El archivo por lotes crea dos certificados en el almacén de certificados CurrentUser/TrustedPeople. El primer certificado tiene un nombre de asunto CN=STS que utiliza el servicio de token de seguridad para firmar los tokens de seguridad que emite el cliente. El segundo certificado tiene un nombre de asunto de CN=localhost y lo usa el servicio de token de seguridad para cifrar un secreto, de modo que el servicio de token de seguridad pueda descifrarlo.

Para configurar, compilar y ejecutar el ejemplo

  1. Ejecute el archivo Setup.cmd para crear los certificados necesarios.

  2. Para compilar la solución, siga las instrucciones que se indican en Compilación de los ejemplos de Windows Communication Foundation. Asegúrese de que todos los proyectos de la solución se construyen, incluidos Shared, RSTRSTR, Service, SecurityTokenService y Client.

  3. Asegúrese de que Service.exe y SecurityTokenService.exe se ejecutan con privilegios de administrador.

  4. Ejecute Client.exe.

Para limpiar después de la muestra.

Ejecute Cleanup.cmd en la carpeta samples una vez que haya terminado de ejecutar el ejemplo.