5 de enero de 2016

Seguridad Transport - Message utilizando wsHttpBinding

WCF Transport Security
Protege la información a través del canal de comunicación entre el cliente y el servidor, el tipo de canal utilizado para enviar la informacion define cual sera el protocolo a utilizar para encriptar y autentificar la información, por ejemplo HTTPS utiliza SSL o bien el que tu especifiques en el binding


Supongamos que utilizaremos un servicio WCF para trabajar en la web utilizando el protocolo HTTP, en este caso HTTPS proporciona integridad, confidencialidad y autenticación de servidor y la seguridad del mensaje SOAP proporciona la autenticación del cliente.De manera predeterminada, se realiza la autenticación del cliente una vez por sesión y los resultados de autenticación están almacenados en la memoria caché durante la duración de la sesión, ejemplo:






WCF Message Security
La seguridad aquí se expresa en que el mensaje es encriptado ante de utilizar cualquiera sea el medio de transporte de la información entre cliente y servidor, de esta forma solo las partes que conocen como desencriptar el mensaje podrán leerlos.

Cuando se crea un servicio WCF y se desea brindar seguridad a nivel de mensaje se deben utilizar certificados digitales de tipo x.509 los cuales brindan un nivel de confianza para el envío de credenciales desde el cliente al servidor, ejemplo:

  
    
      
    
  
antes de comenzar muestro los bindings de WCF y el tipo de seguridad que brindan


En esta entrada se utilizara un WCF Service con wsHttpBinding, este servicio solo expondrá una operacion
public string saludo(string nombre)
 {
  return string.Format("Hola {0} este servicio WCF utiliza wsHttpBinding", nombre);
 }
Se trabajara con un WCF Service hospedado en IIS, también será de importancia en este ejemplo el descargar pluralsight que es una herramienta que ayuda a crear certificados útiles en la etapa de desarrollo, otro aspecto a recalcar que se van a validar credenciales de un cliente(username y password) por tanto se debe agregar la clase UserNameValidator a nuestro servicio WCF, esta clase hereda de de la clase UserNamePasswordValidator y sobreescribe el método Validate, ademas se debe agregar la referencia a la dll System.IdentityModel no solo en el código de la clase sino también "manualmente"
using System;
using System.IdentityModel.Selectors;
using System.IdentityModel.Tokens;

namespace WCFWSBinding
{
 public class UserNameValidator : UserNamePasswordValidator
 {
  public override void Validate(string userName, string password)
  {
   if (string.IsNullOrEmpty(userName))
   throw new ArgumentNullException("userName");
 
   if (string.IsNullOrEmpty(password))
   throw new ArgumentNullException("password");

   if (userName == "Pablo" && password == "Pablo")
   return;
   throw new SecurityTokenException("Unknown Username or Password");
  }
 }
}

Creando el certificado x509

Lo primero sera crear el certificado que se va utilizar ya sea en seguridad WCF modo transporte o seguridad WCF modo message, en esta entrada se utilizara la herramienta PluralSight Self-Cert, lo primero sera descargar la herramienta y ejecutarla en modo administrador


Como nombre utilizare CertWCF y se alojara en mi computadora de trabajo


Al presionar el botón Save tendremos una pantalla con los detalles del certificado recién creado que ademas nos muestra el mensaje que nuestro certificado ha sido creado y guardado, pero si presionamos el botón View Cert... 


nos damos cuenta que nuestro certificado recién creado no es de confianza para la computadora, esto pasa porque un certificado debe ser aprobado por una autoridad certificadora y en esta entrada así como en algunos proyectos de desarrollo se utilizan certificados auto-aprobados, lo que haremos es presionar el botón Install Certificate


seleccionamos Local Machine y presionamos el botón Next


Seleccionamos la primera opcion y luego presionamos el botón Next


para completar la validación de nuestro certificado presionamos el botón Finish


tendremos de nuevo la pantalla con los detalles del certificado, ahor presionamos el botón Browse Store


buscamos en la lista de certificados el CertWCF y damos click sobre este


y podemos verificar que ahora nuestro recién creado certificado si es de confianza para la computadora


Pero aun no terminamos, en la ventana de Command Prompt de Windows escribe mmc y luego enter, aparecerá una ventana de User Account Control, sobre esta presiona el botón Yes



En esta nueva ventana selecciona File --> Add/Remove Snap-in...


Selecciona Certificate en el panel izquierdo y luego presiona el boton Add


selecciona Computer Account y presionar el botón Next


seleccionamos Local Computer


presionar OK


en la carpeta Personal debe aparecer el certificado CertWCF, dar click derecho y copiar


Pegar el certificado en carpeta Trusted People y cerrar


Ahora abrimos el administrador de IIS y sobre nuestro servidor buscamos Server Certificates


Aparecerá nuestro certificado CertWCF recién creado


Lo que sigue es agregar un binding de tipo Https a nuestro sitio web, para ello damos click derecho sobre el sitio y seleccionamos Edit Bindings...


seleccionamos https


y seleccionamos el certificado CertWCF recién creado


El binding recién agregado debe estar disponible para el sitio


Transport Security with Certificate Authentication

the service is hosted under Internet Information Services (IIS) which is configured with Secure Sockets Layer (SSL). The service is configured with an SSL (X.509) certificate to allow clients to verify the identity of the server. The client is also configured with an X.509 certificate that allows the service to verify the identity of the client. The server’s certificate must be trusted by the client and the client’s certificate must be trusted by the server.



Continuando con nuestro ejemplo, se debe especificar que nuestro sitio web exija el utilizar SSL, para ello desde el administrador de IIS nos posicionamos en nuestro servicio WCF y buscamos SSL Settings, dar doble click sobre este y seleccionar Require SSL 



Después de lo anterior viene la configuracion del Web.config, les dejo la configuracion del Web.config que a mi me ha funcionado para trabajar con seguridad WCF en modo transporte, por alguna razón el blogger o el SyntaxHighlighter(que es la herramienta que ocupa para mostrar el código en blogger) me cambia el orden del codigo cuando se trata de XML y ademas me crea la etiqueta system. web="" donde debería ser system.web  y también coloca system. servicemodel="" donde debería ser system.servicemodel, les dejo la imagen de esa parte especifica del Web.config para que lo tengan en cuenta por si no les parece correcta correcta esa etiqueta o por si son los que le dan copy-paste al código(aparte del orden y de las etiquetas mencionadas el código funciona) y después de la imagen que muestra las etiquetas antes mencionadas y el orden de los atributos dejo el código XML de la configuración


  
      
  
  
   
    
      
             
          
          
             
            
          
           
          
         
       
      
    
    
    
      
        
        
        
         
          
             
          
        
      
    

    
      
        
          
          
          
          
            
                 
        
        
      
    
    
    
    
    
    
      
        
          
        
      
    
  
  
    
    
  
  
  
  
    
      
        
          
        
      
      
        
          
        
      
    
    
      
    
    
  

ahora toca agregar un cliente que consumirá nuestro recién creado servicio WCF, para ello utilizare una aplicacion de escritorio y agregare una referencia al servicio WCF utilizando la dirección Https asi:


antes de mostrar el código del cliente para hacer llamado al servicio WCF hay que hacer notar que aunque se haya creado un certificado para pruebas en etapa de desarrollo, este no esta debidamente validado y al IIS no se le puede engañar, asi que cuando hagamos peticiones desde el cliente podemos encontrarnos con este error 


para evitar ese error se debe agregar esta linea de codigo:
System.Net.ServicePointManager.ServerCertificateValidationCallback += (se, cert, chain, sslerror) => true;
pero solo durante la etapa de desarrollo, cuando tu proyecto pase a producción recuerda quitarla y contar con un certificado debidamente validado y quitar la linea de código, aqui esta la llamada al servicio WCF desde el cliente:
private void enlazar_Click(object sender, EventArgs e)
 {
 System.Net.ServicePointManager.ServerCertificateValidationCallback += (se, cert, chain, sslerror) => true;
 string saludo = string.Empty;
 using (pruebaHttps.WSBindingClient proxy = new pruebaHttps.WSBindingClient())
  {
  proxy.ClientCredentials.UserName.UserName = "Pablo";
  proxy.ClientCredentials.UserName.Password = "Pablo";
  try
   {
   saludo = proxy.saludo(txt.Text.ToString());
   MessageBox.Show(saludo);
   }
   catch (Exception ex) {
   MessageBox.Show(ex.Message.ToString());
   }             
  }
 }

Message Security with a User Name Client

Desde el sitio de microsoft https://msdn.microsoft.com/en-us/library/ms731058(v=vs.110).aspx lo exponen de la siguiente manera



Si vienes trabajando desde la seguridad WCF modo transporte(caso contrario dirígete al código XML del Web.config) lo primero a destacar aquí es que ya no se necesita que nuestro servicio WCF requiera SSL así que desmarcamos esta opción desde el IIS Manager


también en el Web.config del servicio WCF se debe cambiar baseaddress="https://localhost/WCFWSBinding/Service1.svc" por baseaddress="http://localhost/WCFWSBinding/Service1.svc"

 
   
  
 

y cambiar el binding="mexHttpsBinding" por binding="mexHttpBinding"

por ultimo cambiar httpsgetenabled="true" por httpgetenabled="true"

La configuración del Web.config queda de la siguiente manera manera, primero muestro la imagen del Web.config y después muestro el código XML, esto lo hago porque les recuerdo mi problema: por alguna razón el blogger o el SyntaxHighlighter(que es la herramienta que ocupa para mostrar el código en blogger) me cambia el orden del código cuando se trata de XML y ademas me crea la etiqueta system. web="" donde debería ser system.web  y también coloca system. servicemodel="" donde debería ser system.servicemodel



y aqui esta el codigo XML 


  
      
  
  
    
      
             
          
          
            
              
            
           
          
        
      
    
    
      
        
          
            
            
          
        
        
        
          
            
          
        
      
    
    
      
        
          
          
          

                   
            
            
           
            
                 
        
        
      
    
    
    
    
      
        
          
        
      
    
  
  
    
    
  
  
  
  
    
      
        
          
        
      
      
        
          
        
      
    
    
      
    
    
  

se agrega una referencia de servicio al cliente, en este ejemplo utilizare una aplicación de Windows Forms como cliente


el código con el que se solicita un método del servicio WCF desde el cliente es
private void enlazar_Click(object sender, EventArgs e)
 {  
  string saludo = string.Empty;
           
   using (pruebaCert.WSBindingClient proxy = new pruebaCert.WSBindingClient())
   {
    proxy.ClientCredentials.UserName.UserName = "Pablo";
    proxy.ClientCredentials.UserName.Password = "Pablo";
     try
     {
     saludo = proxy.saludo(txt.Text.ToString());
     MessageBox.Show(saludo);
     }
     catch (Exception ex)
     {
     MessageBox.Show(ex.Message.ToString());
     }        
   }
 }
y el código en el App.config del cliente(utilizo Windows Forms como cliente) se tiene esta configuración