InicioArticulos y noticiasBases de datosProgramaciónForosInternetServiciosContratacionEmail
También puedes ver ...
Migración de WSE a WCF (Web Services de 2005 a 2008)
WCF: compartición de tipos entre referencias a servicios
Mapa de configuracion de WCF
Cómo consumir un Servicio WCF en vez de un Web Service
¿Que son IPCChannel o el protocolo IPC en WCF?
Web services Extensions 3.0 de Indigo a WCF

Afiliados
La Web del programador
MundoProgramacion


 

WCF: netTcpBinding con seguridad tipo Custom

En una aplicación WCF que vaya a ser desplegada en el entorno de una intranet, el binding más idóneo suele ser netTcpBinding, ya que suele cubrir perfectamente las funcionalidades que se necesitan en aplicaciones de este tipo, manteniendo unas características óptimas en cuanto al protocolo y codificación del mensaje. En este tipo de escenario, no es difícil encontrarse con la necesidad de tener que usar un modelo de seguridad en el que el cliente proporcione las credenciales en forma de un nombre de usuario y contraseña, los cuales se validarán con un método personalizado (Custom) en el servicio; es el caso típico de una aplicación que desarrollemos sin poder asumir que vamos a tener un dominio Windows en el que apoyarnos para realizar la autenticación y autorización. Mientras que es bastante común encontrar muchos ejemplos en los que la seguridad se implementa apoyándose en credenciales tipo Windows, no es así para el escenario que usa las credenciales de usuario y contraseña. Este post intenta recoger los pasos a seguir para ponerlo en marcha usando Visual Studio 2008. 

Por cierto, si os habéis tenido que meter mínimamente con seguridad en WCF habréis visto que es un campo muy amplio en el que nos podemos encontrar muchos casos distintos. Un recurso muy recomendable es la guía de seguridad de WCF que podéis encontrar en codeplex:

http://www.codeplex.com/WCFSecurityGuide

Parte de este post se basa en información que podéis encontrar en dicha guía, en concreto la que trata de certificados.

Paso 1: Creación e instalación de certificados

Para poder usar credenciales de tipo usuario y contraseña con netTcpBinding, WCF requiere que usemos certificados de modo que las credenciales no viajen en texto plano a través de la red.

Como comentaba antes este paso viene bastante bien recogido en la guía de seguridad de WCF (en concreto en el tercer How-to) por lo que voy a intentar ser breve.

En un entorno de producción normalmente usaremos un certificado emitido por una entidad certificadora reconocida, aunque durante el desarrollo podemos usar certificados de prueba generados por nosotros mismos. Para ello el primer paso consiste en crear un certificado que actúe como nuestra entidad certificadora raíz. En la máquina donde vayamos a alojar el servicio, desde una línea de comandos de Visual Studio 2008 ejecutaremos lo siguiente:

 

makecert -n "CN=MiEntidadCertificadora" -r -sv MiEntidadCertificadora.pvk MiEntidadCertificadora.cer

En el parámetro -n indicaremos el nombre (subject) del certificado. El comando nos pedirá las contraseñas para las claves privada y pública del certificado, y generará dos ficheros, uno con la clave privada (extensión .pvk) y otro con el certificado (extensión .cer).

A continuación tendremos que instalar el certificado generado. Abrimos una consola de administración (Inicio - Ejecutar - mmc) y realizamos los siguientes pasos:

1.   Menú File -> Add/Remove Snap-in. Click en Add
2.   Seleccionar Certificates y hacer click en Add
3.   Seleccionar la opción de "Computer account", para que el certificado esté disponible para todos los usuarios, y pulsar Next
4.   Dejar seleccionado "Local computer: (the computer this console is running on)" y pulsar Finish. Cerrar los diálogos que queden abiertos
5.   En el panel de la izquierda, expandir el nodo Certificates (Local Computer) y dentro de él la carpeta "Trusted Root Certification Authorities"
6.   Click derecho sobre la subcarpeta Certificates -> All Tasks -> Import
7.   En la pantalla de "File to Import", click en Browse y abrir el fichero .cer que habíamos generado
8.   En la pantalla "Certificate Store" dejar seleccionado el valor predeterminado

Si estamos desarrollando el servicio y el cliente en la misma máquina, no tenemos que hacer nada más relacionado con la entidad certificadora raíz. Pero si desarrollamos en máquinas distintas, o estamos haciendo un despliegue a otro entorno, hay que tener en cuenta que esta instalación hay que hacerla tanto en la máquina servidora como en todos los clientes. Si no hacemos la instalación en los clientes, no podremos establecer la comunicación porque no se podrá comprobar la validez del certificado usado contra su entidad certificadora.

 

Una vez que hemos instalado el certificado correspondiente a la entidad certificadora raíz, podemos generar el certificado de prueba que utilizaremos en nuestra aplicación WCF. Nuevamente desde una línea de comandos de Visual Studio 2008, en la carpeta donde tengamos los ficheros generados anteriormente, ejecutaremos:

 

makecert -sk <<Nombre único del  certificado>> -iv MiEntidadCertificadora.pvk -n "CN=<<Nombre de la máquina>>" -ic MiEntidadCertificadora.cer -sr localmachine -ss my -sky exchange -pe

Se nos pedirá la contraseña de la clave privada que habíamos introducido previamente al generar el certificado de la entidad certificadora raíz. Con este comando añadiremos al almacén de certificados de la máquina un certificado que nos servirá para cifrar la comunicación de nuestro servicio. En este caso no necesitamos instalar este certificado en los clientes ya que obtendremos una copia codificada en base64 durante la generación del proxy.

Si ya disponemos de un certificado que no sea de prueba (lo cual sería recomendable para el despliegue en producción), podríamos instalarlo de forma similar a como se ha descrito con la consola de administración, lógicamente sin tener que generar nada con la herramienta makecert.

Paso 2: Codificación y configuración del servicio

En la parte del servicio tenemos que ocuparnos de dos tareas: codificar el método Custom que validará el usuario y contraseña recibido del cliente durante el procesamiento de los mensajes entrantes, y configurar el servicio para que use dicho método para la validación, y para que use el certificado para encriptar la conexión.

 

El método Custom para validar el usuario y contraseña recibidos debe incluirse en una clase que deberá heredar de System.IdentityModel.Selectors.UserNamePasswordValidator. En esta clase deberemos sobreescribir el método Validate con el código que realice nuestra validación; el código del método podría ser similar al siguiente:

 

   1: public class Validador : UserNamePasswordValidator
   2: {
   3:     public override void Validate(string userName, string password)
   4:     {
   5:         // Chequeo de parámetros
   6:         if (string.IsNullOrEmpty(userName))
   7:             throw new ArgumentNullException("userName");
   8:         if (string.IsNullOrEmpty(password))
   9:             throw new ArgumentNullException("password");
  10:  
  11:         // Validación del usuario
  12:         if (userName != "test" || password != "test")
  13:             throw new SecurityTokenException("Usuario o contraseña incorrectos");
  14:     }
  15: }

 

Aquí introduciríamos nuestro código que validase al usuario contra la base de datos o cualquier otra fuente que necesitemos.

Para configurar el servicio, tendremos que incluir en el fichero de configuración de nuestro host WCF una sección system.Servicemodel similar a la siguiente:

 

   1: <system.serviceModel>
   2:   <services> 
   3:     <service name="ServicioSeguro.ServicioSeguro"
   4:              behaviorConfiguration="myServiceBehavior">
   5:       
   6:       <endpoint
   7:         address="ServicioSeguro"
   8:         binding="netTcpBinding"
   9:         contract="ServicioSeguro.IServicioSeguro"
  10:         bindingConfiguration ="mySecureBinding" />
  11:       
  12:       <endpoint binding="mexHttpBinding" name="mex" contract="IMetadataExchange" />
  13:       
  14:       <host>
  15:         <baseAddresses>
  16:           <add baseAddress="http://<<Nombre de la máquina>>:8000"/>
  17:           <add baseAddress="net.tcp://<<Nombre de la máquina>>:9000"/>
  18:         </baseAddresses>
  19:       </host>
  20:     
  21:     </service>
  22:     
  23:   </services>
  24:   
  25:   <behaviors>
  26:     <serviceBehaviors>
  27:       <behavior name="myServiceBehavior">
  28:         <serviceMetadata httpGetEnabled="true"/>
  29:           <serviceCredentials>       
  30:             <serviceCertificate findValue="<<Nombre de la máquina>>" 
x509FindType="FindBySubjectName"
  31:                                 storeLocation="LocalMachine" storeName="My" />
  32:  
  33:             <userNameAuthentication userNamePasswordValidationMode="Custom"
  34:               customUserNamePasswordValidatorType="ServicioSeguro.Validador, ServicioSeguro" />
  35:           </serviceCredentials>
  36:       </behavior>
  37:     </serviceBehaviors>
  38:   </behaviors>
  39:   
  40:   <bindings>
  41:     <netTcpBinding>
  42:       <binding name="mySecureBinding">
  43:         <security mode="Message">
  44:           <message clientCredentialType ="UserName"/>
  45:         </security>
  46:       </binding>
  47:     </netTcpBinding>
  48:   </bindings>
  49:   
  50: </system.serviceModel>

En esta sección de configuración podemos ver varios puntos a tener en cuenta:

  • Mediante la sección <bindings>, creamos una configuración personalizada para netTcpBinding llamada mySecureBinding, para usar seguridad a nivel de Mensaje con credenciales usuario/contraseña
  • Mediante la sección <behaviors>, creamos un behavior para el servicio llamado myServiceBehavior, en el que especificamos el certificado a usar mediante el nombre que especificamos al crearlo e instalarlo (el nombre de la máquina en este caso). También especificamos el método que vamos a usar para validar las credenciales. Para esto último usamos su nombre cualificado completo, incluyendo el namespace, y el nombre del ensamblado donde reside

 

En este punto, una vez que alojemos el servicio, los clientes que se quieran comunicar con el mismo deberán encriptar los mensajes con el certificado provisto y proporcionar un nombre de usuario y contraseña válidos para el método Validate que hemos escrito (es decir, que no provoquen una excepción). Si no cumplen estos dos requisitos, no serán capaces de invocar ningún método presente en el contrato expuesto en el endpoint.

 

Paso 3: Codificación y configuración del cliente

En el cliente también tenemos dos tareas a realizar, la configuración del endpoint y el paso de las credenciales desde código.

Una vez que hayamos generado el proxy, ya sea añadiendo la referencia al servicio o usando svcutil, tendremos un fichero de configuración en el cual deberíamos encontrar un endpoint que contendrá el certificado que usa el servicio, codificado en base64:

   1: <identity>
   2:     <certificate encodedValue="AwAAAAEAAAAUAAAAxulv4/Z...........=" />
   3: </identity>

 

De este modo nuestro canal del lado del cliente será capaz de utilizar este certificado para encriptar los mensajes que envíe al servicio. En este mismo fichero de configuración deberemos añadir un behavior para el cliente que especifique el modo de validación y revocación del certificado. Esto es necesario porque como estamos utilizando un certificado de prueba, necesitaremos que sea validado contra nuestra entidad certificadora raíz y que no se compruebe contra una lista de revocación; al pasar a producción esta configuración la cambiaremos por la correspondiente al certificado definitivo. El código de configuración del behavior sería el siguiente; lógicamente tendremos que indicar en el endpoint que se use dicho behavior mediante el atributo behaviorConfiguration:

 

   1: <behaviors>
   2:   <endpointBehaviors>
   3:     <behavior name="ClientCertificateBehavior">
   4:       <clientCredentials>
   5:         <serviceCertificate>
   6:           <authentication
   7:               certificateValidationMode="PeerOrChainTrust" revocationMode ="NoCheck" />
   8:         </serviceCertificate>
   9:       </clientCredentials>
  10:     </behavior>
  11:   </endpointBehaviors>
  12: </behaviors>

 

Por último, necesitamos pasar las credenciales de usuario y contraseña de modo que el servicio pueda comprobarlas para permitir la comunicación. Esto lo haremos usando el miembro ClientCredentials de la clase proxy que se ha generado al añadir la referencia al servicio o al utilizar svcutil. Por ejemplo, si tenemos una instancia de dicha clase proxy llamada miProxy, incluiríamos el siguiente código antes de comenzar a trabajar con los métodos de dicha clase para comunicarnos con el servicio:

 

   1: miProxy.ClientCredentials.UserName.UserName = "test";
   2: miProxy.ClientCredentials.UserName.Password = "test";

Si no ha habido nungún problema en el proceso, con esto podríamos comenzar a utilizar el servicio desde el cliente teniendo la comunicación encriptada a nivel de mensaje, y la forma de autenticar las credenciales que más nos convenga.

Un saludo !!!


 Versión para imprimir  Foros de consulta


Añadir comentario ... Para preguntar utiliza los foros
Autor:

Título:


Para preguntar utiliza los foros.



 Versión para imprimir

WCF: netTcpBinding con seguridad tipo Custom
Autor: Jose LuisSoriaTeruel
Visitas: 455 Fecha de publicación: 15/07/2008
Jose Luis es uno de los mejores profesionales con los que he tenido el gusto de trabajar. Es un técnico excelente y mejor persona.
Es experto en técnologias Microsoft (.Net, SQL Server, C#, ASP.Net ...) y arquitecturas distribuidas (Replicación, Service Broker, WCF ...).
Actualmente trabaja como Developer Advisor en Plain Concepts
Jose Luis publica los contenidos de su blog paralelamente en devjoker.Podeis leer su blog AQUI




Visitas: 302 | Comentarios: 0 | Archivo: Articulos
Categorias: ASP.NET|CSS|ASP.NET
Visitas: 137 | Comentarios: 0 | Archivo: Articulos
Categorias: TFS
Visitas: 101 | Comentarios: 5 | Archivo: Articulos
Categorias: TFS
Visitas: 429 | Comentarios: 4 | Archivo: Articulos
Categorias: Transact-SQL|LinQ
Visitas: 1445 | Comentarios: 6 | Archivo: Articulos
Categorias: Visual Basic .NET|C#|ASP.NET|ASP.NET|Programación|ADO.NET
27/09/2008 Navegando ....
Visitas: 238 | Comentarios: 0 | Archivo: Articulos
Categorias: Humor
Visitas: 611 | Comentarios: 0 | Archivo: Articulos
Categorias: Visual Basic .NET|C#|ASP.NET|ASP.NET|Programación|WCF
Visitas: 2570 | Comentarios: 4 | Archivo: Articulos
Categorias: C#
Visitas: 463 | Comentarios: 0 | Archivo: Articulos
Categorias: JavaScript|ASP.NET
Visitas: 1071 | Comentarios: 0 | Archivo: Articulos
Categorias: Windows XP|Linux|Windows Vista

Útimos temas recibidos en los foros ...
Crystal reports XI Release 2 y asp.net por mvargas ... [ASP.NET] 0 21/11/2008
Enviar un email con C# utilizando .Net FrameWork 2.0 con logo... por Moises ... [ASP.NET] 0 21/11/2008
Enviar un email con C# utilizando .Net FrameWork 2.0 por Moises ... [C#] 0 21/11/2008
Cuestión de BFILE. por Megatron ... [ORACLE] 0 21/11/2008
Enviar email por Dol ... [ASP.NET] 5 21/08/2007
*******PREGUNTA********: por T.S.U.En Informatíca ... [Visual Basic 6.0] 5 17/03/2008
Programar tareas en oracle. por Rodrigo ... [ORACLE] 0 21/11/2008
fechas con datatimepicker por peyin ... [Visual Basic .NET] 3 20/11/2008
agregar datos de un gridview a un textbox por jhors ... [ASP.NET] 3 19/09/2007
Select de sql en c# por Stuart ... [C#] 1 20/11/2008
Manual en Español de SQL Navigator for Oracle por Maira ... [ORACLE] 12 30/03/2008
Como mandar mensaje a Celular por Pako ... [C#] 40 13/03/2007

Access CGI JSP ORACLE UNIX
Actualidad HTML/DHTML/XHTML LINUX PHP Visual Basic .NET
ASP ISAPI MS DOS Power Builder Visual Basic 6.0
ASP.NET Java mySQL SQL WIN 98/NT/2000/XP
C# JavaScript Opinion SQL Server

devjoker  Te recomendamos además ...
21/06/2007 Código embebido en Reporting Services
03/10/2006 Polimorfismo    forma parte de...Tutorial C#
16/04/2007 Mantener variables de Sesión y Aplicación de forma permanente en ASP.net
28/06/2006 Triggers en PL/SQL    forma parte de...Tutorial PL/SQL
01/08/2006 Generar un fichero Excel con C# sin tener Excel instalado
22/10/2005 Indices    forma parte de...Tutorial SQL
02/10/2008 Creando cadenas de conexión ConnectionStrings en .net 3.5 o visual Studio 2008 usando SqlConnectionStringBuilder
10/07/2006 Funciones en PL/SQL    forma parte de...Tutorial PL/SQL
26/07/2006 Secuencias    forma parte de...Tutorial PL/SQL
13/07/2006 Paquetes en PL/SQL    forma parte de...Tutorial PL/SQL

 

Encuesta
¿A que perfil te adaptas mejor?
[Ver] [Votar]