Validador de contraseña de nombre de usuarioUser Name Password Validator

Este ejemplo muestra cómo implementar un validador UserNamePassword personalizado.This sample demonstrates how to implement a custom UserNamePassword Validator. Esto es útil en casos donde ninguno de los modos de validación UserNamePassword integrados es apropiado para los requisitos de la aplicación; por ejemplo, cuando los pares nombre de usuario/contraseña se almacenan en un almacén externo, como una base de datos.This is useful in cases where none of the built-in UserNamePassword Validation modes is appropriate for the requirements of the application; for example, when username/password pairs are stored in some external store, such as a database. Este ejemplo muestra un servicio que tiene un validador personalizado que comprueba dos pares de nombre de usuario y contraseña determinados.This sample shows a service that has a custom validator that checks for two particular username/password pairs. El cliente usa un par de nombre de usuario y contraseña para autenticar en el servicio.The client uses such a username/password pair to authenticate to the service.

Importante

Puede que los ejemplos ya estén instalados en su equipo.The samples may already be installed on your computer. Compruebe el siguiente directorio (predeterminado) antes de continuar.Check for the following (default) directory before continuing.

<InstallDrive>:\WF_WCF_Samples

Si este directorio no existe, vaya a ejemplos de Windows Communication Foundation (WCF) y Windows Workflow Foundation (WF) para .NET Framework 4 para descargar todos los Windows Communication Foundation (WCF) WFWF y ejemplos.If this directory does not exist, go to Windows Communication Foundation (WCF) and Windows Workflow Foundation (WF) Samples for .NET Framework 4 to download all Windows Communication Foundation (WCF) and WFWF samples. Este ejemplo se encuentra en el siguiente directorio.This sample is located in the following directory.

<InstallDrive>:\WF_WCF_Samples\WCF\Extensibility\Security\UserNamePasswordValidator

Nota

Dado que cualquiera puede construir una credencial de nombre de usuario que utilice los pares de nombre de usuario y contraseña que el validador personalizado acepta, el servicio es menos seguro que el comportamiento predeterminado proporcionado por el validador UserNamePassword estándar.Because anyone can construct a Username credential that uses the username/password pairs that the custom validator accepts, the service is less secure than the default behavior provided by the standard UserNamePassword Validator. El validador UserNamePassword estándar intenta asignar el par de nombre de usuario/contraseña proporcionado a una cuenta de Windows y si esta asignación no es correcta, se produce un error en la autenticación.The standard UserNamePassword Validator attempts to map the provided username/password pair to a Windows account and fails authentication if this mapping fails. El validador UserNamePassword personalizado en este ejemplo NO SE DEBE utilizar en el código de producción, solo es para fines informativos.The custom UserNamePassword Validator in this sample MUST NOT be used in production code, it is for illustration purposes only.

En resumen, este ejemplo muestra cómo:In summary this sample demonstrates how:

  • Se puede autenticar el cliente con un token de nombre de usuario.The client can be authenticated using a Username Token.

  • El servidor valida las credenciales del cliente con un UserNamePasswordValidator personalizado y cómo propagar los errores personalizados desde la lógica de validación del nombre de usuario y la contraseña al cliente.The server validates the client credentials against a custom UserNamePasswordValidator and how to propagate custom faults from the username and password validation logic to the client.

  • El servidor se autentica utilizando el certificado X.509 del servidor.The server is authenticated using the server's X.509 certificate.

El servicio expone un punto de conexión único para comunicarse con el servicio, definido usando el archivo de configuración App.config. El punto de conexión está compuesto por una dirección, un enlace y un contrato.The service exposes a single endpoint for communicating with the service, defined using the configuration file, App.config. The endpoint consists of an address, a binding, and a contract. El enlace se configura con un estándar wsHttpBinding que tiene como valor predeterminado el uso de WS-Security y la autenticación de nombre de usuario.The binding is configured with a standard wsHttpBinding that defaults to using WS-Security and username authentication. El comportamiento del servicio especifica el modo Custom para validar los pares de nombre de usuario y contraseña del cliente con el tipo de la clase de validador.The service behavior specifies the Custom mode for validating client username/password pairs along with the type of the validator class. El comportamiento también especifica el certificado de servidor mediante el elemento serviceCertificate.The behavior also specifies the server certificate using the serviceCertificate element. El certificado de servidor debe contener el mismo valor para el SubjectName findValue que en el <> serviceCertificate.The server certificate has to contain the same value for the SubjectName as the findValue in the <serviceCertificate>.

<system.serviceModel>
  <services>
    <service name="Microsoft.ServiceModel.Samples.CalculatorService"
             behaviorConfiguration="CalculatorServiceBehavior">
      <!-- use host/baseAddresses to configure base address provided by host -->
      <host>
        <baseAddresses>
          <add baseAddress ="http://localhost:8001/servicemodelsamples/service" />
        </baseAddresses>
      </host>
      <!-- use base address specified above, provide one endpoint -->
      <endpoint address="username"
                binding="wsHttpBinding"
                bindingConfiguration="Binding"
                contract="Microsoft.ServiceModel.Samples.ICalculator" />
    </service>
  </services>

  <bindings>
    <wsHttpBinding>
      <!-- username binding -->
      <binding name="Binding">
        <security mode="Message">
          <message clientCredentialType="UserName" />
        </security>
      </binding>
    </wsHttpBinding>
  </bindings>

  <behaviors>
    <serviceBehaviors>
      <behavior name="CalculatorServiceBehavior">
        <serviceDebug includeExceptionDetailInFaults ="true"/>
        <serviceCredentials>
          <!--
          The serviceCredentials behavior allows one to
          specify a custom validator for username/password
          combinations.
          -->
          <userNameAuthentication userNamePasswordValidationMode="Custom"
                                  customUserNamePasswordValidatorType="Microsoft.ServiceModel.Samples.CalculatorService+MyCustomUserNameValidator, service" />
          <!--
          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. You must specify a server certificate when passing username/passwords to encrypt the information as it is sent on the wire. Otherwise the username and password information would be sent as clear text. This configuration references the "localhost" certificate installed during the setup instructions.
          -->
          <serviceCertificate findValue="localhost" storeLocation="LocalMachine" storeName="My" x509FindType="FindBySubjectName" />
        </serviceCredentials>
      </behavior>
    </serviceBehaviors>
  </behaviors>

</system.serviceModel>

La configuración de punto de conexión de cliente está compuesta por un nombre de configuración, una dirección absoluta para el punto de conexión de servicio, el enlace y el contrato.The client endpoint configuration consists of a configuration name, an absolute address for the service endpoint, the binding, and the contract. El enlace del cliente se configura con el modo adecuado y el clientCredentialType del mensaje.The client binding is configured with the appropriate mode and message clientCredentialType.

<system.serviceModel>

    <client>
      <!-- Username based endpoint -->
      <endpoint name="Username"
address="http://localhost:8001/servicemodelsamples/service/username"
                binding="wsHttpBinding"
                bindingConfiguration="Binding"
                behaviorConfiguration="ClientCertificateBehavior"
                contract="Microsoft.ServiceModel.Samples.ICalculator">
      </endpoint>
    </client>

    <bindings>
      <wsHttpBinding>
        <!-- Username binding -->
        <binding name="Binding">
          <security mode="Message">
            <message clientCredentialType="UserName" />
          </security>
        </binding>
      </wsHttpBinding>
    </bindings>
    <behaviors>
      <endpointBehaviors>
        <behavior name="ClientCertificateBehavior">
          <clientCredentials>
            <serviceCertificate>
              <!--
            Setting the certificateValidationMode to PeerOrChainTrust means that if the certificate
            is in the user's Trusted People store, then it will be trusted without performing a
            validation of the certificate's issuer chain. This setting is used here for convenience so that the
            sample can be run without having to have certificates issued by a certification authority (CA).
            This setting is less secure than the default, ChainTrust. The security implications of this
            setting should be carefully considered before using PeerOrChainTrust in production code.
            -->
              <authentication certificateValidationMode="PeerOrChainTrust" />
            </serviceCertificate>
          </clientCredentials>
        </behavior>
      </endpointBehaviors>
    </behaviors>

  </system.serviceModel>

La implementación del cliente pide al usuario que introduzca un nombre de usuario y una contraseña.The client implementation prompts the user to enter a username and password.

// Get the username and password
Console.WriteLine("Username authentication required.");
Console.WriteLine("Provide a username.");
Console.WriteLine("   Enter username: (test1)");
string username = Console.ReadLine();
Console.WriteLine("   Enter password:");
string password = "";
ConsoleKeyInfo info = Console.ReadKey(true);
while (info.Key != ConsoleKey.Enter)
{
    if (info.Key != ConsoleKey.Backspace)
    {
        if (info.KeyChar != '\0')
        {
            password += info.KeyChar;
        }
        info = Console.ReadKey(true);
    }
    else if (info.Key == ConsoleKey.Backspace)
    {
        if (password != "")
        {
            password = password.Substring(0, password.Length - 1);
        }
        info = Console.ReadKey(true);
    }
}
for (int i = 0; i < password.Length; i++)
{
    Console.Write("*");
}
Console.WriteLine();
// Create a proxy with Certificate endpoint configuration
CalculatorProxy proxy = new CalculatorProxy("Username")
try
{
  proxy.ClientCredentials.Username.Username = username;
  proxy.ClientCredentials.Username.Password = password;
    // Call the Add service operation.
    double value1 = 100.00D;
    double value2 = 15.99D;
    double result = proxy.Add(value1, value2);
    Console.WriteLine("Add({0},{1}) = {2}", value1, value2, result);
  }
  catch (Exception e)
  {
      Console.WriteLine("Call failed:");
      while (e != null)
      {
          Console.WriteLine("\t{0}", e.Message);
          e = e.InnerException;
      }
      proxy.Abort();
  }
}

Este ejemplo utiliza un UserNamePasswordValidator personalizado para validar pares de nombre de usuario y contraseña.This sample uses a custom UserNamePasswordValidator to validate username/password pairs. El ejemplo implementa CustomUserNamePasswordValidator, derivado de UserNamePasswordValidator.The sample implements CustomUserNamePasswordValidator, derived from UserNamePasswordValidator. Consulte la documentación existente sobre UserNamePasswordValidator para obtener más información.See the documentation for UserNamePasswordValidator for more information. Este ejemplo de validador personalizado determinado implementa el método Validate para aceptar dos pares de nombre de usuario y contraseña determinados tal y como se muestran en el código siguiente.This particular custom validator sample implements the Validate method to accept two particular username/password pairs as shown in the following code.

public class CustomUserNameValidator : UserNamePasswordValidator
{
 // This method validates users. It allows in two users,
 // test1 and test2 with passwords 1tset and 2tset respectively.
 // This code is for illustration purposes only and
 // MUST NOT be used in a production environment because it
 // is NOT secure.
 public override void Validate(string userName, string password)
 {
  if (null == userName || null == password)
  {
   throw new ArgumentNullException();
  }

  if (!(userName == "test1" && password == "1tset") && !(userName == "test2" && password == "2tset"))
  {
   throw new FaultException("Unknown Username or Incorrect Password");
   }
  }
 }

Una vez que se implementa el validador en el código de servicio, se debe informar al host de servicio sobre la instancia del validador que se va a usar.Once the validator is implemented in service code, the service host must be informed about the validator instance to use. Esto se hace mediante el código siguiente.This is done using the following code.

serviceHost.Credentials.UserNameAuthentication.UserNamePasswordValidationMode = UserNamePasswordValidationMode.Custom;
serviceHost.Credentials. UserNameAuthentication.CustomUserNamePasswordValidator = new CustomUserNamePasswordValidator();

O puede hacer lo mismo en la configuración tal y como se explica a continuación.Or you can do the same thing in configuration as follows.

<behaviors>
 <serviceBehaviors>
  <behavior name="CalculatorServiceBehavior">
  ...
   <serviceCredentials>
    <!--
    The serviceCredentials behavior allows one to specify authentication constraints on username / password combinations.
    -->
    <userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="Microsoft.ServiceModel.Samples.CalculatorService+CustomUserNameValidator, service" />
   ...
  </behavior>
 </serviceBehaviors>
</behaviors>

Al ejecutar el ejemplo, las solicitudes y respuestas de la operación se muestran en la ventana de la consola del cliente.When you run the sample, the operation requests and responses are displayed in the client console window. El cliente debería llamar correctamente a todos los métodos.The client should successfully call all the methods. Presione ENTRAR en la ventana de cliente para cerrar el cliente.Press ENTER in the client window to shut down the client.

Instalar el archivo por lotesSetup Batch File

El archivo por lotes Setup.bat incluido con este ejemplo permite configurar el servidor con los certificados pertinentes para ejecutar una aplicación autohospedada que requiera seguridad basada en el certificado del servidor.The Setup.bat batch file included with this sample allows you to configure the server with relevant certificates to run a self-hosted application that requires server certificate-based security. Este archivo por lotes debe modificarse para que funcione en los equipos o en un caso no autohospedado.This batch file must be modified to work across machines or to work in a non-self-hosted case.

A continuación, se proporciona una breve descripción de las diferentes secciones de los archivos por lotes de manera que se puedan modificar para ejecutarse con la configuración adecuada.The following provides a brief overview of the different sections of the batch files so that they can be modified to run in the appropriate configuration.

  • Crear el certificado de servidor:Creating the server certificate:

    Las líneas siguientes del archivo por lotes Setup.bat crean el certificado de servidor que se va a usar.The following lines from the Setup.bat batch file create the server certificate to be used. La variable %SERVER_NAME% especifica el nombre del servidor.The %SERVER_NAME% variable specifies the server name. Cambie esta variable para especificar su propio nombre de servidor.Change this variable to specify your own server name. El valor predeterminado es el host local.The default value is localhost.

    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
    
  • Instalar el certificado del servidor en el almacén de certificados de confianza del cliente:Installing the server certificate into client's trusted certificate store:

    Las líneas siguientes del archivo por lotes Setup.bat copian el certificado de servidor en el almacén de los usuarios de confianza del cliente.The following lines in the Setup.bat batch file copy the server certificate into the client trusted people store. Este paso es necesario porque el sistema cliente no confía implícitamente en los certificados generados por Makecert.exe.This step is required because certificates generated by Makecert.exe are not implicitly trusted by the client system. Si ya tiene un certificado que se basa en un certificado raíz de confianza del cliente (por ejemplo, un certificado emitido por Microsoft), no es necesario el paso de rellenar el almacén de certificados del cliente con el certificado de servidor.If you already have a certificate that is rooted in a client trusted root certificate—for example, a Microsoft issued certificate—this step of populating the client certificate store with the server certificate is not required.

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

Para configurar y compilar el ejemploTo set up and build the sample

  1. Para compilar la solución, siga las instrucciones de creación de los ejemplos de Windows Communication Foundation.To build the solution, follow the instructions in Building the Windows Communication Foundation Samples.

  2. Para ejecutar el ejemplo en una configuración de equipos única o cruzada, utilice las instrucciones siguientes.To run the sample in a single- or cross-machine configuration, use the following instructions.

Para ejecutar el ejemplo en el mismo equipoTo run the sample on the same machine

  1. Ejecute setup. bat desde la carpeta de instalación del ejemplo en un símbolo del sistema de Visual Studio 2012.Run Setup.bat from the sample install folder inside a Visual Studio 2012 command prompt. De esta forma, se instalan todos los certificados necesarios para ejecutar el ejemplo.This installs all the certificates required for running the sample.

    Nota

    El archivo por lotes Setup. bat está diseñado para ejecutarse desde un símbolo del sistema de Visual Studio 2012.The Setup.bat batch file is designed to be run from a Visual Studio 2012 Command Prompt. La variable de entorno PATH establecida en el símbolo del sistema de Visual Studio 2012 apunta al directorio que contiene los archivos ejecutables requeridos por el script Setup. bat.The PATH environment variable set within the Visual Studio 2012 Command Prompt points to the directory that contains executables required by the Setup.bat script.

  2. Inicie Service.exe desde \service\bin.Launch Service.exe from service\bin.

  3. Inicie Client.exe desde \client\bin.Launch Client.exe from \client\bin. La actividad del cliente se muestra en la aplicación de consola del cliente.Client activity is displayed on the client console application.

  4. Si el cliente y el servicio no pueden comunicarse, vea sugerencias para la solución de problemas de ejemplos de WCF.If the client and service are not able to communicate, see Troubleshooting Tips for WCF Samples.

Para ejecutar el ejemplo en los equiposTo run the sample across machines

  1. Cree un directorio en el equipo del servicio para los binarios del servicio.Create a directory on the service machine for the service binaries.

  2. Copie los archivos del programa de servicio en el directorio de servicio situado en el equipo del servicio.Copy the service program files the service directory on the service machine. Copie también los archivos Setup.bat y Cleanup.bat en el equipo del servicio.Also copy the Setup.bat and Cleanup.bat files to the service machine.

  3. Necesita un certificado de servidor con el nombre del sujeto que contiene el nombre de dominio completo del equipo.You need a server certificate with the subject name that contains the fully-qualified domain name of the machine. El archivo de configuración para el servidor debe estar actualizado para reflejar este nuevo nombre del certificado.The configuration file for the server must be updated to reflect this new certificate name.

  4. Copie el certificado de servidor en el almacén CurrentUser-TrustedPeople del cliente.Copy the server certificate into the CurrentUser-TrustedPeople store of the client. Solo necesita hacerlo si el certificado del servidor no está emitido por el emisor de confianza.You need to do this only if the server certificate is not issued by a trusted issuer.

  5. En el archivo App.config situado en el equipo de servicio, cambie el valor de la dirección base para especificar un nombre de equipo completo en lugar del host local.In the App.config file on the service machine, change the value of the base address to specify a fully-qualified machine name instead of localhost.

  6. En el equipo de servicio, inicie Service.exe desde una ventana de símbolo del sistema.On the service machine, launch Service.exe from a command prompt window.

  7. Copie los archivos de programa del cliente de la carpeta \client\bin, en la carpeta específica del lenguaje, al equipo del cliente.Copy the client program files from the \client\bin\ folder, under the language-specific folder, to the client machine.

  8. En el archivo Client.exe.config del equipo cliente, cambie el valor de la dirección del punto de conexión para que coincida con la nueva dirección de su servicio.In the Client.exe.config file on the client machine, change the address value of the endpoint to match the new address of your service.

  9. En el equipo cliente, inicie Client.exe desde la ventana de símbolo del sistema.On the client machine, launch Client.exe from a command prompt window.

  10. Si el cliente y el servicio no pueden comunicarse, vea sugerencias para la solución de problemas de ejemplos de WCF.If the client and service are not able to communicate, see Troubleshooting Tips for WCF Samples.

Para realizar una limpieza después de ejecutar el ejemploTo clean up after the sample

  1. Ejecute Cleanup.bat en la carpeta de ejemplos cuando haya terminado de ejecutar el ejemplo.Run Cleanup.bat in the samples folder once you have finished running the sample. Así se elimina el certificado del servidor del almacén de certificados.This removes the server certificate from the certificate store.