Cómo: Llamar a un servicio Web mediante certificados de cliente en ASP.NET

Publicado: 26 de junio de 2006

Consulte la Página de entrada como punto de partida y para obtener una descripción completa del documento Crear aplicaciones ASP.NET seguras.

Resumen: Los servicios Web admiten la autenticación mediante certificados de cliente como medio para autenticar aplicaciones cliente. En este artículo se muestra cómo configurar un servicio Web para la autenticación mediante certificados de cliente y cómo llamar al servicio Web, pasando un certificado de una aplicación Web ASP.NET.

En los servicios Web suele ser necesaria la posibilidad de autenticar a los llamadores (otras aplicaciones) para poder realizar la autorización. Los certificados de cliente ofrecen un mecanismo de autenticación excelente para los servicios Web. Si se utilizan certificados de cliente, la aplicación se beneficia también de la creación de un canal seguro [en el que se utiliza Secure Sockets Layer (SSL)] entre la aplicación cliente y el servicio Web. Esto le permite enviar de forma segura información confidencial hacia y desde el servicio Web. SSL asegura la integridad y confidencialidad de los mensajes.
En este artículo se describe cómo llamar a un servicio Web que está configurado para requerir certificados de cliente.

Nota

La información de este artículo se aplica también a los componentes remotos alojados en ASP.NET y en IIS.

¿Por qué utilizar un componente revisado?

En la solución que se presenta en este artículo se utiliza un componente revisado configurado para ejecutarse en una aplicación de servidor de Servicios Empresariales con una cuenta de servicio personalizada. La aplicación Web ASP.NET llama al componente revisado, el cual realiza la llamada al servicio Web (y pasa un certificado de cliente). En la ilustración 1 se muestra la configuración de la solución.

imagen

Ilustración 1
ASP.NET llama a un componente revisado para invocar el servicio Web

De esta forma se asegura que el sistema tiene acceso a un perfil de usuario al comunicarse con el servicio Web. El perfil es necesario para el protocolo de enlace SSL inicial.

Nota

la cuenta ASPNET que se utiliza para ejecutar aplicaciones Web tiene el privilegio "Denegar el inicio de sesión interactivo", que impide el inicio de sesión de forma interactiva. Como consecuencia, la cuenta no tiene un perfil de usuario.
No conceda la capacidad de inicio de sesión interactivo a la cuenta ASPNET (ni a ninguna otra cuenta que se utilice para ejecutar aplicaciones Web). Respete siempre el principio de privilegios mínimos al configurar cuentas para ejecutar aplicaciones Web y conceda a las cuentas los mínimos privilegios posibles. Para obtener más información, consulte "Cómo: Crear una cuenta personalizada para ejecutar ASP.NET" en la sección Referencia de esta guía.

¿Por qué se requiere un perfil de usuario?

Cuando se realiza una solicitud a un servicio Web que requiere certificados de cliente, se produce un protocolo de enlace SSL entre el cliente y el servidor. Algunos de los componentes intercambiados son el certificado de servidor, el certificado de cliente y un “secreto maestro previo” que genera el cliente. El secreto se utiliza posteriormente en el protocolo para generar un “secreto maestro”.
Para que el servidor pueda comprobar que el presentador del certificado es realmente el titular de la clave privada, el cliente debe cifrar el secreto maestro previo con la clave privada y enviar el secreto cifrado al servidor. Para que el sistema pueda tener acceso a la clave privada del cliente para firmar el secreto maestro previo, debe tener acceso a la clave privada en el almacén de claves del cliente. El almacén de claves se encuentra en el perfil del cliente, que debe estar cargado.

Requisitos

A continuación se describen las recomendaciones de hardware, software, infraestructura de red, conocimientos y Service Pack que se necesitan.
Sistema operativo Microsoft® Windows® 2000
Sistema de desarrollo Microsoft Visual Studio® .NET
Acceso a una entidad emisora de certificados (CA, Certificate Authority) para generar nuevos certificados
Un servidor Web que tenga instalado un certificado de servidor
Para obtener más información acerca de cómo instalar certificados de servidor Web, consulte "Cómo: Configurar SSL en un servidor Web".
Para llevar a cabo los procedimientos de este artículo, también es necesario que tenga conocimientos de la herramienta de desarrollo Microsoft Visual C#™.

Nota

en este artículo, el equipo en el que reside el servicio Web se llama "WSServer" y el equipo cliente del servicio Web (en el que reside la aplicación Web ASP.NET de cliente y el componente revisado) se llama "WSClient".

En esta página

Crear un servicio Web sencillo Crear un servicio Web sencillo
Configurar el directorio virtual del servicio Web para requerir certificados de cliente Configurar el directorio virtual del servicio Web para requerir certificados de cliente
Crear una cuenta personalizada para ejecutar un componente revisado Crear una cuenta personalizada para ejecutar un componente revisado
Solicitar un certificado de cliente para la cuenta personalizada Solicitar un certificado de cliente para la cuenta personalizada
Probar el certificado de cliente con un explorador Probar el certificado de cliente con un explorador
Exportar el certificado de cliente a un archivo Exportar el certificado de cliente a un archivo
Desarrollar el componente revisado que se utiliza para llamar al servicio Web Desarrollar el componente revisado que se utiliza para llamar al servicio Web
Configurar e instalar el componente revisado Configurar e instalar el componente revisado
Desarrollar una aplicación Web para llamar al componente revisado Desarrollar una aplicación Web para llamar al componente revisado
Recursos adicionales Recursos adicionales

Crear un servicio Web sencillo

Para crear un servicio Web sencillo en el equipo host de servicios Web

  1. Inicie Visual Studio .NET y cree una nueva aplicación de servicio Web ASP.NET en C# con el nombre SecureMath.

  2. Cambie el nombre de service1.asmx por math.asmx.

  3. Abra math.asmx.cs y cambie el nombre de la clase Service1 por math.

  4. Agregue a la clase math el siguiente método Web.

    [WebMethod]
         public long Add(long operand1, long operand2)
         { 
         return (operand1 + operand2);
         }
    
  5. En el menú Generar, haga clic en Generar solución para crear el servicio Web.

Configurar el directorio virtual del servicio Web para requerir certificados de cliente

En este procedimiento se utiliza Servicios de Internet Information Server para configurar el directorio virtual del servicio Web para SSL y para requerir certificados.En este procedimiento se supone que dispone de un certificado válido instalado en el servidor Web. Para obtener más información acerca de cómo instalar certificados de servidor Web, consulte "Cómo: Configurar SSL en un servidor Web" en la sección Referencia de esta guía.

Para configurar el directorio virtual del servicio Web para requerir certificados de cliente

  1. Inicie Servicios de Internet Information Server en el equipo host de servicios Web.

  2. Vaya al directorio virtual SecureMath.

  3. Haga clic con el botón secundario del mouse (ratón) en SecureMath y, a continuación, haga clic en Propiedades.

  4. Haga clic en la ficha Seguridad de directorios.

  5. En Comunicaciones seguras, haga clic en Modificar.

    Si el botón Modificar no está disponible, lo más probable es que no tenga instalado un certificado de servidor Web

  6. Active la casilla de verificación Requerir canal seguro (SSL).

  7. Seleccione la opción Requerir certificados de cliente.

  8. Haga clic en Aceptar y, a continuación, haga clic de nuevo en Aceptar.

  9. En el cuadro de diálogo Omitir herencia, haga clic en Seleccionar todo y, después, haga clic en Aceptar para cerrar el cuadro de diálogo de propiedades de SecureMath.

    De esta forma se aplica la nueva configuración de seguridad a todos los subdirectorios contenidos en la raíz del directorio virtual.

Crear una cuenta personalizada para ejecutar un componente revisado

En este procedimiento se crea una nueva cuenta de usuario en el equipo cliente del servicio Web que se utilizará para ejecutar el componente revisado que llama al servicio Web.

Para crear una cuenta personalizada para ejecutar el componente revisado

  1. Cree una nueva cuenta de usuario con una contraseña segura en el equipo cliente. Desactive la casilla de verificación El usuario debe cambiar la contraseña en el siguiente inicio de sesión y, después, active la casilla La contraseña nunca caduca.

  2. Agregue la cuenta al grupo Administradores.

    La cuenta que se utiliza para cargar un perfil de usuario debe ser una cuenta de administrador en el equipo local.

Solicitar un certificado de cliente para la cuenta personalizada

En este procedimiento se iniciará sesión en el equipo cliente con la nueva cuenta personalizada. Después se emitirá una solicitud de certificado. Además se supone que se están utilizando los Servicios de Microsoft Certificate Server. Si no está utilizando los Servicios de Microsoft Certificate Server para crear nuevos certificados, envíe una solicitud de certificado de cliente a la CA que prefiera e instale el certificado durante una sesión iniciada con la cuenta personalizada.
En este procedimiento también se supone que los Servicios de Microsoft Certificate Server están configurados para emitir automáticamente certificados como respuesta a las solicitudes de certificados. También se pueden configurar para solicitudes pendientes, las cuales requieren que un administrador emita explícitamente el certificado.

Para comprobar la configuración de los Servicios de Microsoft Certificate Server

  1. En el equipo donde residen los Servicios de Microsoft Certificate Server, haga clic en Entidad emisora de certificados dentro del grupo de programas Herramientas administrativas.

  2. Expanda Entidad emisora de certificados (local), haga clic con el botón secundario del mouse (ratón) en la entidad y, a continuación, haga clic en Propiedades.

  3. Haga clic en la ficha Módulo de directivas y, después, haga clic en Configurar.

  4. Compruebe la acción predeterminada.

    En el siguiente procedimiento se supone que la opción Emitir siempre el certificado está seleccionada.

Para solicitar un certificado de cliente para la cuenta personalizada

  1. Cierre la sesión en el equipo cliente y vuelva a iniciarla con la cuenta personalizada.
    Esto fuerza la creación de un perfil de usuario para la cuenta personalizada.

  2. Vaya a la CA para solicitar un certificado de cliente. Por ejemplo, si la CA se encuentra en el equipo CAServer, vaya a la siguiente ubicación.

    http://caserver/certsrv
    
  3. Haga clic en Solicitar un certificado y, después, en Siguiente.

  4. Asegúrese de que la opción Certificado de usuario está seleccionada y, después, haga clic en Siguiente.

  5. Haga clic en Enviar. Se genera una solicitud y se envía a la CA para su procesamiento.

  6. Después de emitirse el certificado y de que reciba una respuesta del servidor CA, haga clic en Instalar este certificado.

  7. Asegúrese de que el certificado de la entidad emisora se instala como una entidad emisora de certificados raíz de confianza en el equipo local.
    Para confirmarlo, lleve a cabo los siguientes pasos:
    a. En la barra de tareas, haga clic en el botón Inicio y, después, en Ejecutar.
    b. Escriba mmc y, a continuación, haga clic en Aceptar.
    c. En el menú Archivo, haga clic en Agregar o quitar complemento.
    d. Haga clic en Agregar.
    e. Haga clic en Certificados y, después, en Agregar.
    f. Haga clic en Cuenta de equipo y, después, en Siguiente.
    g. Haga clic en Equipo local: (el equipo en el que se ejecuta esta consola) y, después, haga clic en Finalizar.
    h. Haga clic en Cerrar y, a continuación, en Aceptar.
    i. En el panel izquierdo del complemento MMC, expanda Certificados (equipo local).
    j. Expanda Entidades emisoras de certificados raíz de confianza y, a continuación, haga clic en Certificados.
    k. Confirme que el certificado de la CA aparece en la lista.

  8. Si no aparece, lleve a cabo los siguientes pasos:
    a. Vaya a la dirección http://caserver/certsrv.
    b. Haga clic en Recuperar el certificado de entidad emisora de certificados o la lista de revocación de certificados y, a continuación, haga clic en Siguiente.
    c. Haga clic en Instalar esta ruta de certificación de CA.

Probar el certificado de cliente con un explorador

En este procedimiento se utilizará el explorador para conectar con el servicio Web con el fin de confirmar que no hay problemas con los certificados de servidor o cliente.

Para probar el certificado de cliente con un explorador

  1. Utilice Internet Explorer para ir a la dirección https://server/SecureMath/Math.asmx.
    Asegúrese de especificar "https", ya que el sitio está configurado para requerir SSL.

  2. Debe aparecer el cuadro de diálogo Autenticación del cliente. Seleccione el certificado de cliente y haga clic en Aceptar.

  3. Confirme que la página de prueba del servicio Web se muestra correctamente en el explorador.

    Si aparece el cuadro de diálogo que se muestra en la ilustración 2, necesitará instalar el certificado de la entidad emisora en el almacén Entidades emisoras de certificados raíz de confianza, como se describió en el procedimiento anterior.

    imagen

    Ilustración 2

    Cuadro de diálogo Alerta de seguridad

Exportar el certificado de cliente a un archivo

En este procedimiento se exporta el certificado de cliente a un archivo. Posteriormente, el componente revisado lo recuperará cuando necesite pasar el certificado al servicio Web.

Para exportar el certificado de cliente a un archivo

  1. En Internet Explorer, haga clic en Opciones de Internet en el menú Herramientas.

  2. Haga clic en la ficha Contenido.

  3. Haga clic en Certificados.

  4. Haga clic en el certificado de cliente y, después, en Exportar.

  5. Haga clic en Siguiente para pasar el cuadro de diálogo inicial del Asistente para exportación de certificados.

  6. Compruebe que está seleccionada la opción No exportar la clave privada y, a continuación, haga clic en Siguiente.

  7. Asegúrese de que está seleccionada la opción DER binario codificado X.509 (.CER) y, después, haga clic en Siguiente.

    Debe utilizar este formato porque .NET Framework no admite los formatos Base 64 ni PKCS #7.

  8. Escriba un nombre para el archivo de exportación. Anote la ubicación del archivo de exportación .cer, ya que la necesitará en un procedimiento posterior.

  9. Haga clic en Siguiente y, después, en Finalizar para exportar el certificado.

  10. Cierre Internet Explorer.

  11. Cierre la sesión en el equipo y vuelva a iniciarla con su cuenta de desarrollo habitual.

Desarrollar el componente revisado que se utiliza para llamar al servicio Web

En este procedimiento se crea una nueva aplicación de biblioteca de clases en C# y se crea el componente revisado que se utiliza para llamar al servicio Web. Se supone que está trabajando en el equipo cliente.

Para desarrollar el componente revisado que se utiliza para llamar al servicio Web

  1. Inicie Visual Studio .NET y cree un nuevo proyecto de biblioteca de clases en C# con el nombre WebServiceRequestor.

  2. Agregue una referencia Web al servicio Web SecureMath.
    Importante: debe cambiar temporalmente la configuración del directorio virtual del servicio Web para no requerir certificados de cliente (pero sí requerir SSL), antes de agregar la referencia Web. Después de agregar correctamente la referencia Web, cambie de nuevo la configuración del directorio virtual para requerir certificados de cliente.

    En la práctica, si un sitio requiere certificados de cliente, el editor del servicio hace que el archivo WSDL esté disponible como un archivo sin conexión independiente, que los consumidores (del servicio) pueden utilizar para crear el servidor proxy.
    En el cuadro de diálogo Agregar referencia Web, asegúrese de que utiliza https al especificar la ubicación del servicio Web. En caso contrario, se producirá un error porque el directorio virtual del servicio Web está configurado para requerir SSL.

  3. Agregue una referencia al ensamblado System.EnterpriseServices.

  4. Cambie el nombre de class1.cs por ProfileManager.cs.

  5. Agregue a ProfileManager.cs la siguiente definición de clase (reemplazando la clase class1 esqueleto). En la clase ProfileManager se utiliza P/Invoke para llamar a las API Win32 LoadUserProfile y UnloadUserProfile.

    internal class ProfileManager
         {
         [DllImport("Userenv.dll", SetLastError=true, 
         CharSet=System.Runtime.InteropServices.CharSet.Auto)]
         internal static extern bool LoadUserProfile(IntPtr hToken, 
         ref PROFILEINFO lpProfileInfo);
    
    [DllImport("Userenv.dll", SetLastError=true, 
         CharSet=System.Runtime.InteropServices.CharSet.Auto)]
         internal static extern bool UnloadUserProfile(IntPtr hToken, 
         IntPtr hProfile);
    
    [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi)]
         public struct PROFILEINFO
         {
         public int dwSize; 
         public int dwFlags; 
         public String lpUserName; 
         public String lpProfilePath; 
         public String lpDefaultPath; 
         public String lpServerName; 
         public String lpPolicyPath; 
         public IntPtr hProfile; 
         }
         }
    
  6. Agregue al proyecto un segundo archivo de clase con el nombre MathServiceComponent.cs.

  7. Agregue a MathServiceComponent.cs las siguientes instrucciones using debajo de la instrucción using existente.

    using System.Net;
         using System.Web.Services;
         using System.Security.Principal;
         using System.EnterpriseServices;
         using System.Runtime.InteropServices;
         using System.Security.Cryptography.X509Certificates;
         using WebServiceRequestor.WebReference1;
    
  8. Agregue la siguiente definición de clase, que proporciona un método CallMathWebService público. En un procedimiento posterior se llamará a este método desde una aplicación Web ASP.NET de cliente.

    // This class calls the web service that requires a certificate.
         public class MathServiceComponent : ServicedComponent
         {
         [DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError=true)]
         private extern static bool DuplicateToken(IntPtr ExistingTokenHandle, 
         int SECURITY_IMPERSONATION_LEVEL,
         ref IntPtr DuplicateTokenHandle);
    
    [DllImport("kernel32.dll", CharSet=CharSet.Auto)]
         private extern static bool CloseHandle(IntPtr handle);
    
    // Calls the Web service that requires client certificates
         // certFilepath points to the .cer file to use
         // url is the Web service url
         // operand1 and operand2 are the parameters to pass to the Web service
         public long CallMathWebService(String certFilepath, 
         String url, int operand1, int operand2)
         {
         bool retVal = false;
         // Need to duplicate the token. LoadUserProfile needs a token with 
         // TOKEN_IMPERSONATE and TOKEN_DUPLICATE.
         const int SecurityImpersonation = 2;
         IntPtr dupeTokenHandle = DupeToken(WindowsIdentity.GetCurrent().Token,
         SecurityImpersonation);
         if(IntPtr.Zero == dupeTokenHandle)
         {
         throw new Exception("Unable to duplicate token.");
         }
         // Load the profile.
         ProfileManager.PROFILEINFO profile = new ProfileManager.PROFILEINFO();
         profile.dwSize = 32;
         profile.lpUserName = @"alexmlaptop\CustomASPNET";
         retVal = ProfileManager.LoadUserProfile(dupeTokenHandle, ref profile);
         if(false == retVal)
         {
         throw new Exception("Error loading user profile. " + 
         Marshal.GetLastWin32Error());
         }
         // Instantiate the Web service proxy
         math mathservice = new math();
         mathservice.Url = url;
         String certPath = certFilepath;
         mathservice.ClientCertificates.Add(
         X509Certificate.CreateFromCertFile(certPath));
         long lngResult = 0;
         try
         {
         lngResult = mathservice.Add(operand1, operand2);
         }
         catch(Exception ex)
         {
         if(ex is WebException)
         {
         WebException we = ex as WebException;
         WebResponse webResponse = we.Response;
         throw new Exception("Exception calling method. " + ex.Message);
         }
         }
         ProfileManager.UnloadUserProfile(WindowsIdentity.GetCurrent().Token, 
         profile.hProfile);
         CloseHandle(dupeTokenHandle);
         return lngResult;
         }
    
    private IntPtr DupeToken(IntPtr token, int Level)
         {
         IntPtr dupeTokenHandle = new IntPtr(0);
         bool retVal = DuplicateToken(token, Level, ref dupeTokenHandle);
         if (false == retVal)
         { 
         return IntPtr.Zero;
         }
         return dupeTokenHandle;
         }
         } // end class
    
  9. En el menú Generar, haga clic en Generar solución.

Configurar e instalar el componente revisado

En este procedimiento se configura el componente revisado, se genera un nombre seguro, se instala en la caché de ensamblados global y se registra con COM+.

  1. Abra el archivo assemblyinfo.cs y agregue la siguiente instrucción using debajo de las instrucciones using existentes.

    using System.EnterpriseServices;
    
  2. Agregue al archivo assemblyinfo.cs el siguiente atributo de nivel de ensamblado para configurar el componente revisado para que se ejecute en una aplicación de servidor COM+.

    [assembly: ApplicationActivation(ActivationOption.Server)]
    
  3. Abra una ventana del símbolo del sistema y cambie al directorio del proyecto actual.

  4. Utilice la herramienta sn.exe para generar un archivo de claves que contenga un par de claves pública y privada.

    sn.exe -k WebServiceRequestor.snk
    
  5. Vuelva a Visual Studio .NET.

  6. En el archivo assemblyinfo.cs, busque el atributo [AssemblyKeyFile] y modifíquelo para que haga referencia al archivo de claves que se encuentra en el directorio del proyecto, como se indica a continuación.

    [assembly: AssemblyKeyFile(@"..\..\WebServiceRequestor.snk")]
    
  7. En el menú Generar, haga clic en Generar solución.

  8. Vuelva al símbolo del sistema y ejecute el siguiente comando para agregar el ensamblado a la caché de ensamblados global.

    gacutil.exe /i bin\debug\webservicerequestor.dll
    
  9. Ejecute el siguiente comando para registrar el ensamblado con COM+.

    regsvcs bin\debug\webservicerequestor.dll
    
  10. Inicie Servicios de componentes (que se encuentra en el grupo de programas Herramientas administrativas).

  11. Expanda los nodos Servicios de componentes, Equipos y Mi PC.

  12. Expanda la carpeta Aplicaciones COM+.

  13. Haga clic con el botón secundario en WebServiceRequestor y, a continuación, haga clic en Propiedades.

  14. Haga clic en la ficha Identidad.

  15. Seleccione la opción Este usuario: y escriba los detalles correspondientes a la cuenta personalizada que creó anteriormente.

    De esta forma se configura la aplicación COM+ para que se ejecute con la cuenta personalizada.

  16. Haga clic en Aceptar para cerrar el cuadro de diálogo Propiedades.

  17. Cierre Servicios de componentes.

Desarrollar una aplicación Web para llamar al componente revisado

En este procedimiento se crea una sencilla aplicación Web ASP.NET que se utilizará como aplicación cliente para llamar al servicio Web (mediante el componente revisado).

Para desarrollar una aplicación Web para llamar al componente revisado

  1. En el equipo cliente del servicio Web, cree una nueva aplicación Web ASP.NET en C# con el nombre SecureMathClient.

  2. Agregue una referencia a System.EnterpriseServices.

  3. Agregue una referencia al componente revisado WebServiceRequestor.

    Vaya al archivo WebServiceRequestor.dll que se encuentra en la carpeta bin\debug dentro del directorio del proyecto WebServiceRequestor.

  4. Abra el archivo WebForm1.aspx.cs y agregue la siguiente instrucción using debajo de las instrucciones using existentes.

    using WebServiceRequestor;
    
  5. Vea WebForm1.aspx en el modo del diseñador y cree el formulario que se muestra en la ilustración 3 con los siguientes Id.:
    operand1
    operand2
    resultadd

    imagen

    Ilustración 3
    Organización de los controles del formulario Web

  6. Haga doble clic en Add (Sumar) para crear un controlador de eventos de clic.

  7. Agregue al controlador de eventos el siguiente código.

    Nota: establezca la cadena certPath en la ubicación del archivo de certificado que exportó en el procedimiento 6, "Exportar el certificado de cliente a un archivo".

    Configure la cadena url con la dirección URL HTTPS del servicio Web.

       private void add_Click(object sender, System.EventArgs e)
       {
       // TODO: Replace with a valid path to your certificate
       string certPath = @"C:\CustomAccountCert.cer";
       // TODO: Replace with a valid URL to your Web service
       string url = "https://wsserver/securemath/math.asmx";
       MathServiceComponent mathComp = new MathServiceComponent();
       
       long addResult = mathComp.CallMathWebService( certPath, 
       url, 
       Int32.Parse(operand1.Text), 
       Int32.Parse(operand2.Text));
       result.Text = addResult.ToString();
       }
    
  8. En el menú Generar, haga clic en Generar solución.

  9. Ejecute la aplicación. Escriba dos números para sumar y, después, haga clic en Add.

    La aplicación Web llamará al componente revisado, que a su vez llamará al servicio Web mediante SSL y pasará el certificado de cliente.

Recursos adicionales

Para obtener más información, consulte "Cómo: Configurar SSL en un servidor Web" en la sección Referencia de esta guía.

Mostrar: