Partekatu bidez


Servicio de fachada confiable

En el ejemplo TrustedFacade se muestra cómo fluir la información de identidad del autor de la llamada de un servicio a otro mediante la infraestructura de seguridad de Windows Communication Foundation (WCF).

Es un patrón de diseño común para exponer la funcionalidad proporcionada por un servicio a la red pública mediante un servicio de fachada. El servicio de fachada normalmente reside en la red perimetral (también conocida como red perimetral, zona desmilitarizada y subred filtrada) y se comunica con un servicio back-end que implementa la lógica de negocios y tiene acceso a datos internos. El canal de comunicación entre el servicio de fachada y el servicio back-end pasa por un firewall y normalmente se limita solo para un único propósito.

Este ejemplo consta de los siguientes componentes:

  • Cliente de calculadora

  • Servicio de fachada de calculadora

  • Servicio back-end de calculadora.

El servicio de interfaz es responsable de validar la solicitud y autenticar al solicitante. Después de la autenticación y validación correctas, reenvía la solicitud al servicio back-end mediante el canal de comunicación controlado desde la red perimetral a la red interna. Como parte de la solicitud reenviada, el servicio de fachada incluye información sobre la identidad del llamador para que el servicio back-end pueda utilizar esta información en su procesamiento. La identidad del autor de la llamada se transmite mediante un Username token de seguridad dentro del encabezado del mensaje Security . En el ejemplo se usa la infraestructura de seguridad de WCF para transmitir y extraer esta información del Security encabezado.

Importante

El servicio back-end confia en el servicio de fachada para autenticar el llamador. Debido a esto, el servicio back-end no autentica de nuevo al autor de la llamada; utiliza la información de identidad proporcionada por el servicio de fachada en la solicitud reenviada. Debido a esta relación de confianza, el servicio back-end debe autenticar el servicio de fachada para asegurarse de que el mensaje reenviado procede de un origen de confianza, en este caso, el servicio de fachada.

Implementación

Hay dos rutas de comunicación en este ejemplo. En primer lugar, entre el cliente y el servicio de fachada, el segundo es entre el servicio de fachada y el servicio back-end.

Ruta de comunicación entre el cliente y el servicio de fachada

El cliente a la ruta de comunicación de servicio de fachada utiliza wsHttpBinding con un tipo de credencial de cliente UserName . Esto significa que el cliente utiliza nombre de usuario y contraseña para autenticarse al servicio de fachada y el servicio de fachada utiliza el certificado X.509 para autenticarse al cliente. La configuración de enlace es similar al ejemplo siguiente.

<bindings>
  <wsHttpBinding>
    <binding name="Binding1">
      <security mode="Message">
        <message clientCredentialType="UserName"/>
      </security>
    </binding>
  </wsHttpBinding>
</bindings>

El servicio de fachada autentica el llamador mediante la implementación UserNamePasswordValidator personalizada. Con fines de demostración, la autenticación solo garantiza que el nombre de usuario del autor de la llamada coincida con la contraseña presentada. En la situación real, es probable que el usuario se autentique mediante Active Directory o el proveedor de pertenencia personalizado ASP.NET. La implementación del validador reside en FacadeService.cs el archivo .

public class MyUserNamePasswordValidator : UserNamePasswordValidator
{
    public override void Validate(string userName, string password)
    {
        // check that username matches password
        if (null == userName || userName != password)
        {
            Console.WriteLine("Invalid username or password");
            throw new SecurityTokenValidationException(
                       "Invalid username or password");
        }
    }
}

El validador personalizado se configura para ser utilizado dentro del comportamiento serviceCredentials en el archivo de configuración de servicio de fachada. Este comportamiento también se usa para configurar el certificado X.509 del servicio.

<behaviors>
  <serviceBehaviors>
    <behavior name="FacadeServiceBehavior">
      <!--The serviceCredentials behavior allows you to define -->
      <!--a service certificate. -->
      <!--A service certificate is used by the service to  -->
      <!--authenticate itself to its clients and to provide  -->
      <!--message protection. -->
      <!--This configuration references the "localhost"  -->
      <!--certificate installed during the setup instructions. -->
      <serviceCredentials>
        <serviceCertificate
               findValue="localhost"
               storeLocation="LocalMachine"
               storeName="My"
               x509FindType="FindBySubjectName" />
        <userNameAuthentication userNamePasswordValidationMode="Custom"
            customUserNamePasswordValidatorType=
           "Microsoft.ServiceModel.Samples.MyUserNamePasswordValidator,
            FacadeService"/>
      </serviceCredentials>
    </behavior>
  </serviceBehaviors>
</behaviors>

Ruta de comunicación entre el servicio de fachada y el servicio backend

La ruta de comunicación entre el servicio de fachada y el servicio back-end utiliza customBinding que está compuesto por varios elementos de enlace. Esta vinculación logra dos cosas. Autentica el servicio de fachada y el servicio back-end para asegurarse de que la comunicación es segura y procede de un origen de confianza. Además, también transmite la identidad del autor de la llamada inicial dentro del Username token de seguridad. En este caso, solo se transmite el nombre de usuario del autor de la llamada inicial al servicio back-end, la contraseña no se incluye en el mensaje. Esto se debe a que el servicio back-end confía en el servicio de fachada para autenticar al autor de la llamada antes de reenviar la solicitud a él. Dado que el servicio intermediario se autentica al servicio de fondo, el servicio de fondo puede confiar en la información contenida en la solicitud reenviada.

A continuación se muestra la configuración de enlace para esta ruta de comunicación.

<bindings>
  <customBinding>
    <binding name="ClientBinding">
      <security authenticationMode="UserNameOverTransport"/>
      <windowsStreamSecurity/>
      <tcpTransport/>
    </binding>
  </customBinding>
</bindings>

El elemento de enlace <security> se ocupa de la transmisión y extracción del nombre de usuario del llamador. WindowsStreamSecurity<> y <tcpTransport> se encargan de autenticar servicios de fachada y back-end y protección de mensajes.

Para reenviar la solicitud, la implementación del servicio fachada debe proporcionar el nombre de usuario del llamante inicial, de modo que la infraestructura de seguridad de WCF pueda incluirlo en el mensaje reenviado. El nombre de usuario del llamador inicial se proporciona en la implementación del servicio de fachada estableciéndolo en la propiedad ClientCredentials en la instancia del proxy de cliente que el servicio de fachada utiliza para comunicarse con el servicio back-end.

En el código siguiente se muestra cómo el método GetCallerIdentity se implementa en el servicio de fachada. Otros métodos usan el mismo patrón.

public string GetCallerIdentity()
{
    CalculatorClient client = new CalculatorClient();
    client.ClientCredentials.UserName.UserName = ServiceSecurityContext.Current.PrimaryIdentity.Name;
    string result = client.GetCallerIdentity();
    client.Close();
    return result;
}

Como se muestra en el código anterior, la contraseña no se establece en la ClientCredentials propiedad , solo se establece el nombre de usuario. La infraestructura de seguridad de WCF crea un token de seguridad de nombre de usuario sin una contraseña en este caso, que es exactamente lo que se requiere en este escenario.

En el servicio back-end, se debe autenticar la información contenida en el token de seguridad de nombre de usuario. De forma predeterminada, la seguridad de WCF intenta asignar el usuario a una cuenta de Windows mediante la contraseña proporcionada. En este caso, no se proporciona ninguna contraseña y no se requiere el servicio back-end para autenticar el nombre de usuario porque el servicio de fachada ya realizó la autenticación. Para implementar esta funcionalidad en WCF, se proporciona un personalizado UserNamePasswordValidator que solo exige que se especifique un nombre de usuario en el token y no realice ninguna autenticación adicional.

public class MyUserNamePasswordValidator : UserNamePasswordValidator
{
    public override void Validate(string userName, string password)
    {
        // Ignore the password because it is empty,
        // we trust the facade service to authenticate the client.
        // Accept the username information here so that the
        // application gets access to it.
        if (null == userName)
        {
            Console.WriteLine("Invalid username");
            throw new
             SecurityTokenValidationException("Invalid username");
        }
    }
}

El validador personalizado se configura para ser utilizado dentro del comportamiento serviceCredentials en el archivo de configuración de servicio de fachada.

<behaviors>
  <serviceBehaviors>
    <behavior name="BackendServiceBehavior">
      <serviceCredentials>
        <userNameAuthentication userNamePasswordValidationMode="Custom"
           customUserNamePasswordValidatorType=
          "Microsoft.ServiceModel.Samples.MyUserNamePasswordValidator,
           BackendService"/>
      </serviceCredentials>
    </behavior>
  </serviceBehaviors>
</behaviors>

Para extraer la información del nombre de usuario e información sobre la cuenta de servicio de fachada confiable, la implementación del servicio back-end utiliza la clase ServiceSecurityContext . El código siguiente muestra cómo se implementa el GetCallerIdentity método.

public string GetCallerIdentity()
{
    // Facade service is authenticated using Windows authentication.
    //Its identity is accessible.
    // On ServiceSecurityContext.Current.WindowsIdentity.
    string facadeServiceIdentityName =
          ServiceSecurityContext.Current.WindowsIdentity.Name;

    // The client name is transmitted using Username authentication on
    //the message level without the password
    // using a supporting encrypted UserNameToken.
    // Claims extracted from this supporting token are available in
    // ServiceSecurityContext.Current.AuthorizationContext.ClaimSets
    // collection.
    string clientName = null;
    foreach (ClaimSet claimSet in
        ServiceSecurityContext.Current.AuthorizationContext.ClaimSets)
    {
        foreach (Claim claim in claimSet)
        {
            if (claim.ClaimType == ClaimTypes.Name &&
                                   claim.Right == Rights.Identity)
            {
                clientName = (string)claim.Resource;
                break;
            }
        }
    }
    if (clientName == null)
    {
        // In case there was no UserNameToken attached to the request.
        // In the real world implementation the service should reject
        // this request.
        return "Anonymous caller via " + facadeServiceIdentityName;
    }

    return clientName + " via " + facadeServiceIdentityName;
}

La información de cuenta de servicio de fachada se extrae utilizando la propiedad ServiceSecurityContext.Current.WindowsIdentity . Para acceder a la información sobre el autor de la llamada inicial, el servicio back-end usa la ServiceSecurityContext.Current.AuthorizationContext.ClaimSets propiedad . Busca una notificación Identity con un tipo Name. La infraestructura de seguridad de WCF genera automáticamente esta notificación a partir de la información contenida en el Username token de seguridad.

Ejecución del ejemplo

Al ejecutar el ejemplo, las solicitudes de operación y las respuestas se muestran en la ventana de la consola del cliente. Presione ENTRAR en la ventana del cliente para apagar el cliente. Puede presionar Entrar en las ventanas de la consola de servicio de fachada y back-end para cerrar los servicios.

Username authentication required.
Provide a valid machine or domain ac
   Enter username:
user
   Enter password:
****
user via MyMachine\testaccount
Add(100,15.99) = 115.99
Subtract(145,76.54) = 68.46
Multiply(9,81.25) = 731.25
Divide(22,7) = 3.14285714285714

Press <ENTER> to terminate client.

El archivo por lotes Setup.bat incluido con el ejemplo de escenario de fachada de confianza le permite configurar el servidor con un certificado pertinente para ejecutar el servicio de fachada, que requiere seguridad basada en certificados para autenticarse con el cliente. Consulte el procedimiento de instalación al final de este tema para obtener más información.

A continuación se proporciona una breve introducción a las distintas secciones de los archivos por lotes.

  • Creación del certificado de servidor.

    Las líneas siguientes del archivo por lotes de Setup.bat crean el certificado de servidor que se va a usar.

    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
    

    La %SERVER_NAME% variable especifica el nombre del servidor: el valor predeterminado es localhost. El certificado se almacena en el almacén localMachine.

  • Instalar el certificado del servicio de fachada en el almacén de certificados de confianza de cliente.

    La línea siguiente copia el certificado del servicio de fachada en el almacén de personas de confianza del cliente. Este paso es necesario porque el sistema cliente no confía implícitamente en los certificados generados por Makecert.exe. Si ya tiene un certificado que se basa en un certificado raíz de confianza de cliente (por ejemplo, un certificado emitido por Microsoft), este paso para rellenar el almacén de certificados de cliente con el certificado de servidor no es necesario.

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

Para configurar, compilar y ejecutar el ejemplo

  1. Asegúrese de que ha realizado el procedimiento de instalación única para los ejemplos de Windows Communication Foundation.

  2. Para compilar el código C# o Visual Basic .NET Edition de la solución, siga las instrucciones de Building the Windows Communication Foundation Samples.

Para ejecutar el ejemplo en la misma máquina

  1. Asegúrese de que la ruta de acceso incluye la carpeta donde se encuentra Makecert.exe.

  2. Ejecute Setup.bat desde la carpeta de instalación de ejemplo. Esto instala todos los certificados necesarios para ejecutar el ejemplo.

  3. Inicie el BackendService.exe desde el directorio \BackendService\bin en una ventana de consola independiente.

  4. Inicie el FacadeService.exe desde el directorio \FacadeService\bin en una ventana de consola independiente.

  5. Inicie Client.exe desde \client\bin. La actividad de cliente se muestra en la aplicación de consola cliente.

  6. Si el cliente y el servicio no pueden comunicarse, consulte Sugerencias de solución de problemas para ejemplos de WCF.

Para limpiar después de la muestra.

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