Certificado de seguridad de mensaje
El ejemplo MessageSecurity muestra cómo implementar una aplicación que utiliza WS-Security con la autenticación de certificado X.509 v3 para el cliente y requiere la autenticación del servidor con el certificado X.509 v3 del servidor. Este ejemplo utiliza la configuración predeterminada de tal modo que todos los mensajes de la aplicación entre el cliente y el servidor se firman y cifran. Este ejemplo se basa en el ejemplo WSHttpBinding y consiste en un programa de consola de cliente y una biblioteca de servicios hospedados por Internet Information Services (IIS). El servicio implementa un contrato que define un modelo de comunicación de solicitud y respuesta.
Nota
El procedimiento de instalación y las instrucciones de compilación de este ejemplo se encuentran al final de este tema.
El ejemplo muestra cómo controlar la autenticación mediante la configuración y cómo obtener la identidad del llamador a partir del contexto de seguridad, como se muestra en el siguiente código de ejemplo.
public class CalculatorService : ICalculator
{
public string GetCallerIdentity()
{
// The client certificate is not mapped to a Windows identity by default.
// ServiceSecurityContext.PrimaryIdentity is populated based on the information
// in the certificate that the client used to authenticate itself to the service.
return ServiceSecurityContext.Current.PrimaryIdentity.Name;
}
...
}
El servicio expone un punto de conexión para comunicar con el servicio y un punto de conexión para exponer el documento WSDL del servicio mediante el protocolo WS-MetadataExchange, definido utilizando el archivo de configuración (Web.config). El punto de conexión está compuesto por una dirección, un enlace y un contrato. El enlace se configura con un elemento <wsHttpBinding> estándar, que usa la seguridad de mensaje de forma predeterminada. Este ejemplo establece el atributo clientCredentialType
para certificar que se requiere la autenticación del cliente.
<system.serviceModel>
<protocolMapping>
<add scheme="http" binding="wsHttpBinding"/>
</protocolMapping>
<bindings>
<wsHttpBinding>
<!--
This configuration defines the security mode as Message and
the clientCredentialType as Certificate.
-->
<binding>
<security mode ="Message">
<message clientCredentialType="Certificate" />
</security>
</binding>
</wsHttpBinding>
</bindings>
<!--For debugging purposes set the includeExceptionDetailInFaults attribute to true-->
<behaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpGetEnabled="True"/>
<serviceDebug includeExceptionDetailInFaults="False" />
<!--
The serviceCredentials behavior allows one 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" />
<clientCertificate>
<!--
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" />
</clientCertificate>
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
El comportamiento especifica las credenciales del servicio que se utilizan cuando el cliente autentica el servicio. El nombre de sujeto del certificado del servidor se especifica en el atributo findValue
en el elemento <serviceCredentials>.
<!--For debugging purposes, set the includeExceptionDetailInFaults attribute to true.-->
<behaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpGetEnabled="True"/>
<serviceDebug includeExceptionDetailInFaults="False" />
<!--
The serviceCredentials behavior allows one 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" />
<clientCertificate>
<!--
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" />
</clientCertificate>
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
La configuración de punto de conexión de cliente está compuesta de una dirección absoluta para el punto de conexión de servicio, el enlace y el contrato. El enlace del cliente se configura con el modo de seguridad y el modo de autenticación apropiados. Si se trata de un escenario de varios equipos, asegúrese de que se cambie la dirección del punto de conexión de servicio según corresponda.
<system.serviceModel>
<client>
<!-- Use a behavior to configure the client certificate to present to the service. -->
<endpoint address="http://localhost/servicemodelsamples/service.svc" binding="wsHttpBinding" bindingConfiguration="Binding1" behaviorConfiguration="ClientCertificateBehavior" contract="Microsoft.Samples.Certificate.ICalculator"/>
</client>
<bindings>
<wsHttpBinding>
<!--
This configuration defines the security mode as Message and
the clientCredentialType as Certificate.
-->
<binding name="Binding1">
<security mode="Message">
<message clientCredentialType="Certificate"/>
</security>
</binding>
</wsHttpBinding>
</bindings>
...
</system.serviceModel>
La implementación del cliente puede establecer el certificado que se debe utilizar, bien sea a través del archivo de configuración o a través de código. El ejemplo siguiente muestra cómo establecer el certificado para utilizar en el archivo de configuración.
<system.serviceModel>
...
<behaviors>
<endpointBehaviors>
<behavior name="ClientCertificateBehavior">
<!--
The clientCredentials behavior allows one to define a certificate to present to a service.
A certificate is used by a client to authenticate itself to the service and provide message integrity.
This configuration references the "client.com" certificate installed during the setup instructions.
-->
<clientCredentials>
<clientCertificate findValue="client.com" storeLocation="CurrentUser" storeName="My" x509FindType="FindBySubjectName"/>
<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 certificate 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>
El ejemplo siguiente muestra cómo llamar al servicio en su programa.
// Create a client.
CalculatorClient client = new CalculatorClient();
// Call the GetCallerIdentity service operation.
Console.WriteLine(client.GetCallerIdentity());
...
//Closing the client gracefully closes the connection and cleans up resources.
client.Close();
Al ejecutar el ejemplo, las solicitudes y respuestas de la operación se muestran en la ventana de la consola del cliente. Presione ENTRAR en la ventana de cliente para cerrar el cliente.
CN=client.com
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 los ejemplos de Message Security permite configurar el cliente y el servidor con los certificados pertinentes para ejecutar una aplicación hospedada que exija seguridad basada en certificado. El archivo por lotes se puede ejecutar en tres modos. Para ejecutarlo en el modo de equipo único, escriba setup.bat en el Símbolo del sistema para desarrolladores de Visual Studio; para el modo de servicio, escriba setup.bat service; y para el modo de cliente, escriba setup.bat client. Utilice el modo de cliente y servidor cuando ejecute el ejemplo en varios equipos. Para obtener más detalles, vea el procedimiento de configuración al final de este tema. A continuación se proporciona una descripción breve de las diferentes secciones de los archivos por lotes con objeto de que se puedan modificar para ejecutarse con la configuración adecuada.
Crear el certificado del cliente.
La línea siguiente en el archivo por lotes crea el certificado de cliente. El nombre de cliente especificado se utiliza en el nombre del asunto del certificado creado. El certificado se guarda en el almacén
My
, en la ubicación de almacenamientoCurrentUser
.echo ************ echo making client cert echo ************ makecert.exe -sr CurrentUser -ss MY -a sha1 -n CN=%CLIENT_NAME% -sky exchange -pe
Instalar el certificado de cliente en el almacén de certificados de confianza del servidor.
La línea siguiente del archivo por lotes copia el certificado de cliente en el almacén TrustedPeople del servidor para que el servidor pueda tomar decisiones basadas en la confianza o la ausencia de la misma. Para que un servicio de Windows Communication Foundation (WCF) confíe en un certificado instalado en el almacén TrustedPeople, el modo de validación del certificado del cliente debe establecerse en
PeerOrChainTrust
oPeerTrust
. Vea el ejemplo de configuración de servicio anterior para obtener información sobre cómo lograrlo con un archivo de configuración.echo ************ echo copying client cert to server's LocalMachine store echo ************ certmgr.exe -add -r CurrentUser -s My -c -n %CLIENT_NAME% -r LocalMachine -s TrustedPeople
Crear el certificado de servidor.
Las líneas siguientes del archivo por lotes 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 variable %SERVER_NAME% especifica el nombre del servidor. El certificado se almacena en el almacén LocalMachine. Si el archivo por lotes Setup.bat se ejecuta con un argumento de servicio (por ejemplo, setup.bat service), % SERVER_NAME% contiene el nombre de dominio completo del equipo. De lo contrario, tiene como valor predeterminado el host local.
Instalar el certificado del servidor en el almacén de certificados de confianza del cliente.
La línea siguiente copia el certificado de servidor 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 del cliente, por ejemplo, un certificado emitido por Microsoft, no es necesario el paso de rellenar el almacén del certificado de cliente con el certificado de servidor.
certmgr.exe -add -r LocalMachine -s My -c -n %SERVER_NAME% -r CurrentUser -s TrustedPeople
Conceder permisos sobre la clave privada del certificado.
Las líneas siguientes del archivo Setup.bat hacen que el certificado de servidor que está almacenado en el almacén LocalMachine sea accesible para la cuenta de proceso de trabajo ASP.NET.
echo ************ echo setting privileges on server certificates echo ************ for /F "delims=" %%i in ('"%ProgramFiles%\ServiceModelSampleTools\FindPrivateKey.exe" My LocalMachine -n CN^=%SERVER_NAME% -a') do set PRIVATE_KEY_FILE=%%i set WP_ACCOUNT=NT AUTHORITY\NETWORK SERVICE (ver | findstr /C:"5.1") && set WP_ACCOUNT=%COMPUTERNAME%\ASPNET echo Y|cacls.exe "%PRIVATE_KEY_FILE%" /E /G "%WP_ACCOUNT%":R iisreset
Nota
Si usa una edición de Windows que no esté en inglés de Estados Unidos, debe modificar el archivo Setup.bat y reemplazar el nombre de cuenta "NT AUTHORITY\NETWORK SERVICE" por su equivalente regional.
Nota
Las herramientas utilizadas en este archivo por lotes se encuentran en C:\Program Files\Microsoft Visual Studio 8\Common7\tools o C:\Program Files\Microsoft SDKs\Windows\v6.0\bin Uno de estos directorios debe estar en su ruta de acceso del sistema. Si tiene Visual Studio instalado, la manera más fácil de obtener este directorio en la ruta de acceso es abrir el Símbolo del sistema para desarrolladores de Visual Studio. Haga clic en Inicio y seleccione Todos los programas, Visual Studio 2012, Herramientas. Este símbolo del sistema tiene las rutas de acceso adecuadas ya configuradas. De lo contrario, debe agregar manualmente el directorio correcto a su ruta de acceso.
Configurar, compilar y ejecutar el ejemplo
Asegúrese de que ha realizado el procedimiento de instalación única para los ejemplos de Windows Communication Foundation.
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 el mismo equipo
Abra el Símbolo del sistema para desarrolladores de Visual Studio con privilegios de administrador y ejecute Setup.bat desde la carpeta de instalación del ejemplo. De esta forma, se instalan todos los certificados necesarios para ejecutar el ejemplo.
Nota
El archivo por lotes Setup.bat está diseñado para ejecutarse desde el Símbolo del sistema para desarrolladores de Visual Studio. Requiere que la variable de entorno path señale al directorio donde está instalado el SDK. Esta variable de entorno se establece de forma automática en el Símbolo del sistema para desarrolladores de Visual Studio (2010).
Para comprobar el acceso al servicio, introduzca la dirección
http://localhost/servicemodelsamples/service.svc
en un explorador.Inicie Client.exe desde \client\bin. La actividad del cliente se muestra en la aplicación de consola del cliente.
Si el cliente y el servicio no se pueden comunicar, consulte Sugerencias para la solución de problemas de ejemplos de WCF.
Para ejecutar el ejemplo en varios equipos
Cree un directorio en el equipo del servicio. Cree una aplicación virtual denominada "servicemodelsamples" para este directorio utilizando la herramienta de administración de Internet Information Services (IIS).
Copie los archivos de programa de servicio del directorio \inetpub\wwwroot\servicemodelsamples al directorio virtual del equipo de servicio. Asegúrese de que copia los archivos en el subdirectorio \bin. Copie también los archivos Setup.bat, Cleanup.bat e ImportClientCert.bat en el equipo del servicio.
Cree un directorio en el equipo cliente para los archivos binarios del cliente.
Copie los archivos de programa del cliente en el directorio del cliente en el equipo cliente. Copie también los archivos Setup.bat, Cleanup.bat e ImportServiceCert.bat en el cliente.
En el servidor, ejecute setup.bat service en el Símbolo del sistema para desarrolladores de Visual Studio con privilegios de administrador. Al ejecutar setup.bat con el argumento service, se crea un certificado del servicio con el nombre de dominio completo del equipo y se exporta a un archivo denominado Service.cer.
Modifique el archivo Web.config para reflejar el nuevo nombre del certificado (en el atributo
findValue
de <serviceCertificate>), que es igual que el nombre de dominio completo del equipo.Copie el archivo Service.cer del directorio de servicio al directorio del cliente en el equipo cliente.
En el cliente, ejecute setup.bat client en el Símbolo del sistema para desarrolladores de Visual Studio con privilegios de administrador. Al ejecutar setup.bat con el argumento client, se crea un certificado de cliente denominado client.com y se exporta a un archivo denominado Client.cer.
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. Para hacerlo, reemplace el host local con el nombre de dominio completo del servidor.
Copie el archivo Client.cer del directorio del cliente en el directorio del servicio en el servidor.
En el cliente, ejecute ImportServiceCert.bat desde el Símbolo del sistema para desarrolladores de Visual Studio con privilegios de administrador. Así se importa el certificado del servicio del archivo Service.cer en el almacén CurrentUser - TrustedPeople.
En el servidor, ejecute ImportClientCert.bat en el Símbolo del sistema para desarrolladores de Visual Studio con privilegios de administrador. De esta forma se importa el certificado del cliente desde el archivo Client.cer al almacén LocalMachine - TrustedPeople.
En el equipo cliente, inicie Client.exe desde una ventana de símbolo del sistema. Si el cliente y el servicio no se pueden comunicar, consulte Sugerencias para la solución de problemas de ejemplos de WCF.
Para realizar una limpieza después de ejecutar el ejemplo
Ejecute Cleanup.bat en la carpeta de ejemplos después de que haya terminado de ejecutar el ejemplo.
Nota
Este script no quita los certificados del servicio en un cliente cuando el ejemplo se ejecuta en varios equipos. Si ha ejecutado ejemplos de Windows Communication Foundation (WCF) que usan certificados en varios equipos, asegúrese de borrar los certificados de servicio que se hayan instalado en el almacén CurrentUser - TrustedPeople. Para ello, use el siguiente comando:
certmgr -del -r CurrentUser -s TrustedPeople -c -n <Fully Qualified Server Machine Name>
Por ejemplo:certmgr -del -r CurrentUser -s TrustedPeople -c -n server1.contoso.com
.