Certificado de seguridad de mensajes
El ejemplo de MessageSecurity muestra cómo implementar una aplicación que usa WS-Security con la autenticación de certificados X.509 v3 para el cliente y requiere autenticación de servidor mediante el certificado X.509 v3 del servidor. En este ejemplo se usa la configuración predeterminada para que todos los mensajes de aplicación entre el cliente y el servidor estén firmados y cifrados. Este ejemplo se basa en el WSHttpBinding y consta de un programa de consola cliente y una biblioteca de servicios hospedada por Internet Information Services (IIS). El servicio implementa un contrato que define un patrón de comunicación de solicitud-respuesta.
Nota
El procedimiento de instalación y las instrucciones de compilación de este ejemplo se encuentran al final de este tema.
En el ejemplo se muestra cómo controlar la autenticación mediante la configuración y cómo obtener la identidad del autor de la llamada desde el contexto de seguridad, como se muestra en el código de ejemplo siguiente.
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 comunicarse con el servicio y un punto de conexión para exponer el documento WSDL del servicio mediante el protocolo WS-MetadataExchange, definido mediante 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 estándar <wsHttpBinding>, que usa de forma predeterminada la seguridad del mensaje. En este ejemplo se establece el atributo clientCredentialType
en Certificate para requerir la autenticación de 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 usan cuando el cliente autentica el servicio. El nombre del firmante del certificado de servidor se especifica en el atributo findValue
del 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 del punto de conexión de cliente consta de una dirección absoluta para el punto de conexión de servicio, el enlace y el contrato. El enlace de cliente se configura con el modo de seguridad y el modo de autenticación adecuados. Al ejecutarse en un escenario entre equipos, asegúrese de que la dirección del punto de conexión de servicio se cambie en consecuencia.
<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 va a usar, ya sea a través del archivo de configuración o mediante código. En el ejemplo siguiente se muestra cómo establecer el certificado que se va a usar 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>
En el ejemplo siguiente se muestra cómo llamar al servicio en el 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 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.
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 Setup.bat archivo por lotes incluido con los ejemplos de seguridad de mensajes permite configurar el cliente y el servidor con certificados pertinentes para ejecutar una aplicación hospedada que requiera seguridad basada en certificados. 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. Use el modo de cliente y servidor al ejecutar el ejemplo entre equipos. 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 para que se puedan modificar para que se ejecuten en la configuración adecuada:
Creación del certificado de cliente.
La siguiente línea del archivo por lotes crea el certificado de cliente. El nombre del cliente especificado se usa en el nombre del sujeto 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 siguiente línea del archivo por lotes copia el certificado de cliente en el almacén TrustedPeople del servidor para que el servidor pueda tomar las decisiones de confianza o sin confianza pertinentes. Para que un certificado instalado en el almacén TrustedPeople sea de confianza para un servicio de Windows Communication Foundation (WCF), el modo de validación de certificados de cliente debe establecerse en
PeerOrChainTrust
oPeerTrust
. Consulte el ejemplo de configuración del servicio anterior para obtener información sobre cómo se puede hacer mediante 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
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 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 (como setup.bat servicio), el %SERVER_NAME% contiene el nombre de dominio completo del equipo. De lo contrario, el valor predeterminado es localhost.
Instalar el certificado de 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 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
Conceder permisos en la clave privada del certificado.
Las siguientes líneas del archivo Setup.bat hacen que el certificado de servidor almacenado en el almacén LocalMachine sea accesible para la cuenta de proceso de trabajo de 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 estás utilizando una edición de Windows en inglés que no sea de EE. UU., debes editar el archivo Setup.bat y reemplazar el nombre de cuenta "NT AUTHORITY\NETWORK SERVICE" por su equivalente regional.
Nota
Las herramientas usadas en este archivo por lotes se encuentran en C:\Archivos de programa\Microsoft Visual Studio 8\Common7\tools o C:\Archivos de programa\Microsoft SDKs\Windows\v6.0\bin. Uno de estos directorios debe estar en la 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 adecuado a su ruta.
Para 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. Esto instala 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 apunte 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 mediante un explorador, escriba la dirección
http://localhost/servicemodelsamples/service.svc
.Inicie Client.exe desde \client\bin. La actividad de cliente se muestra en la aplicación de consola cliente.
Si el cliente y el servicio no pueden comunicarse, consulte Sugerencias de solución de problemas para ejemplos de WCF.
Para ejecutar el ejemplo entre equipos
Cree un directorio en el equipo de servicio. Cree una aplicación virtual denominada servicemodelsamples para este directorio mediante la herramienta de administración de Internet Information Services (IIS).
Copie los archivos de programa de servicio de \inetpub\wwwroot\servicemodelsamples en el directorio virtual del equipo de servicio. Asegúrese de copiar los archivos en el subdirectorio \bin. Copie también los archivos Setup.bat, Cleanup.baty ImportClientCert.bat en el equipo de servicio.
Cree un directorio en el equipo cliente para los archivos binarios del cliente.
Copie los archivos de programa cliente en el directorio cliente del equipo cliente. Copie también los archivos Setup.bat, Cleanup.baty 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 del servicio, se crea un certificado de servicio con el nombre de dominio completo del equipo y se exporta el certificado de servicio a un archivo denominado Service.cer.
Edite Web.config para que refleje el nuevo nombre de certificado (en el atributo
findValue
del <serviceCertificate>) que coincida con el nombre de dominio completo del equipo.Copie el archivo Service.cer del directorio de servicio en el directorio cliente del 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 cliente y el argumento, se crea un certificado 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 dirección del punto de conexión para que coincida con la nueva dirección del servicio. Para ello, reemplace localhost por el nombre de dominio completo del servidor.
Copie el archivo Client.cer del directorio cliente en el directorio de servicio del 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. Esto importa el certificado de cliente del archivo Client.cer en el 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 pueden comunicarse, consulte Sugerencias de solución de problemas para ejemplos de WCF.
Para limpiar después de la muestra
Ejecute Cleanup.bat en la carpeta samples una vez que haya terminado de ejecutar el ejemplo.
Nota
Este script no quita certificados de servicio en un cliente al ejecutar este ejemplo entre equipos. Si ha ejecutado ejemplos de Windows Communication Foundation (WCF) que usan certificados entre equipos, asegúrese de borrar los certificados de servicio que se han 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
.