Borja Lázaro de Rafael

Consultor tecnológico de desarrollo de proyectos informáticos.

Ingeniero en Informática

Puedes encontrarme en Autentia: Ofrecemos servicios de soporte a desarrollo, factoría y formación

Somos expertos en Java/J2EE

Ver todos los tutoriales del autor

Fecha de publicación del tutorial: 2009-02-09

Tutorial visitado 31.720 veces Descargar en PDF
WSS (Web Service Security) - Autenticación por usuario y contraseña

WSS (Web Service Security) - Autenticación por usuario y contraseña

Índice de contenido

Introducción

En este tutorial vamos a ver como crear un servicio web seguro con autenticación mediante usuario y contraseña. En primer lugar tenemos que tener en cuenta que WS-Security no es un nuevo tipo de servicios web ni de seguridad. WS-Security define cómo utilizar los tokens de seguridad, XML Signature y Xml Encryption en los mensajes SOAP para proporcionar autenticación, confidencialidad e integridad a los Servicios Web.

En el caso que nos ocupa, vamos a centrarnos únicamente en la autenticación del usuario mediante un token de usuario y contraseña. Debemos saber que en WS-Security también existen otros tipos de autenticación basados en certificados X509, tickets de Kerberos, etc. que no vamos a ver en este tutorial.

Entorno

El tutorial está escrito usando el siguiente entorno:

Instalación de Axis2.

En este tutorial de nuestro compañero Iván nos explica la creación de servicios web con Axis2, por lo que toda la preparación del entorno es la misma, así que sólamente vamos a recordar brévemente la instalación del módulo web de Axis2 que nos va a servir como motor de servicios web.

Nos descargarmos la distribución en WAR de Axis2 que viene comprimida, y lo único que tenemos que hacer es descomprimir el fichero "axis2-1.4.1-war.zip" y copiar en el directorio "webapps" de nuestro tomcat el fichero axis2.war. Al arrancar el tomcat desplegará esta aplicación y ya tendremos nuestro motor de servicios web funcionando.

Para comprobar que todo ha ido correctamente podemos ir a http://localhost:8080/axis2/axis2-web/HappyAxis.jsp y comprobar que todo funciona correctamente.

NOTA: Si teneís instalado algún antivirus, es posible que os corte la comunicación de las peticiones a los servicios web. No se exáctamente porqué, pero en mi caso las peticiones http a páginas web funcionaban correctamente, pero las peticiones a servicios web no lo hacían, por lo que tuve que cambiar la configuración del antivirus. Se puede detectar si en la página "HappyAxis" os sale un mensaje como este:


O si ejecutáis un cliente java podéis obtener un error como éste:
     org.apache.axis2.AxisFault: com.ctc.wstx.exc.WstxEOFException: Unexpected EOF in prolog
     at [row,col {unknown-source}]: [1,0]
     ...
    

Ya sabéis, cosas de los antivirus :(.

Hasta aquí lo que hemos conseguido es tener la instalación de servicios web normal, pero nos falta incluirle las extensiones que soporten WS-Security. Para esto nos vamos ha descargar la implementación a href="http://ws.apache.org/rampart/">Apache Rampart, concretamente la versión 1.4. Este módulo es el módulo de seguridad para axis2, y en su página podéis encontrar toda la especificación del mismo.

Para instalar el módulo de Rampart, descomprimimos el fichero ZIP que nos hemos descargado, y lo único que tenemos que hacer es copiarnos todas las librerías (JAR's) del directorio "lib" de la distribución de Rampart al directorio "WEB-INF/lib" de nuestra instalación de Axis2 y los ficheros del directorio "modules" de la distribución de Rampart al directorio "WEB-INF/modules" de la instalación de Axis2.

Ahora ya tenemos instalado nuestro motor de servicios web con el soporte de seguridad definido en WS-Security.

Creación del servicio.

Para crear el servicio vamos a crearnos un nuevo proyecto de Maven, de esta forma podemos aprovechar no sólo la gestión de dependencias, también utilizaremos el plugin de empaquetamiento para generar archivos ".aar" (Axis ARchive, equivalente a los ".jar"). Si quereís ver como se instala el plugin de Maven (Q4E) para eclipse podéis ver este tutorial de nuestro compañero Alejandro.

Creamos un nuevo proyecto de Maven para el servicio web, seleccionamos

El plugin nos generará la siguiente estructura, donde vamos a eliminar las clases "App.java" y "AppTest.java" que nos crea.

Modicamos el pom.xml

Ahora vamos a modificar el fichero "pom.xml" para utilizar el plugin "axis2-aar-maven-plugin". Con este plugin vamos a empaquetar el proyecto directamente como un fichero "aar" que podremos desplegar como servicio web directamente. Podéis ver cómo indicamos que el fichero "services.xml" que crearemos en el directorio "src/main/config" lo incluya en el directorio "META-INF" y servira como descriptor del servicio para Axis2.

También crearemos la dependencia con WSS4J, necesaria para incluir la seguridad a nuestro servicio web.

Clase del servicio

Ahora vamos a crear la clase que va a proporcionar el servicio. En este caso es un servicio de echo "Echo.java", que como véis no tiene ningún misterio, donde indicaremos la configuración de seguridad será en el fichero descriptor del servicio.

Descriptor del servicio

Para desplegar el servicio en Axis2, nos creamos un fichero descriptor del mismo. En este caso seguimos la estructura que hemos indicado en nuestro fichero "pom.xml", y creamos el fichero "services.xml" en el directorio "src/main/config".

En este fichero, además de descripbir el servicio, vamos a incluir una política de seguridad para comprobar la autenticación de quién está llamando al servicio. Esto lo hacemos en dos partes, una indicando la configuración de seguridad de autenticación mediante usuario y contraseña. Y otra configurando adecuadamente el módulo de Rampart, que hemos visto que va a ser el encargado de resolver la seguridad de nuestro servicio web.

En la configuración de Rampart, indicaremos la clase responsable de comprobar los usuarios y contraseñas con el elemento "passwordCallBackClass".

Clase de comprobación de usuario y contraseña

Lo único que nos queda por implementar en nuestro servicio es la clase que comprueba el usuario y contraseña de las peticiones de servicio. Nos creamo la clase "com.autentia.wss.usertoken.service.PWCBHandler" que hemos configurado en el descriptor del servicio para que se encargue de dicha tarea. Esta clase debe heredar de "javax.security.auth.callback.CallbackHandler" y el tipo de "callback" que va a procesar es del tipo "org.apache.ws.security.WSPasswordCallback".

El código de nuestra clase es:

Despliegue del servicio

Para desplegar el servicio primero empaquetamos ejecutando el siguiente comando de Maven en la consola, situándonos en el directorio raíz del proyecto.
mvn package

Esto nos generará el fichero "WSSUserTokenService-1.0-SNAPSHOT.aar" en el directorio "target" de nuestro proyecto. Ahora sólo nos queda copiar dicho fichero al directorio "WEB-INF/services" de la instalación de Axis2 y se desplegará nuestro servicio que podremos comprobar en la administración web de Axis2, y vemos que tiene vinculado el módulo de Rampart.

Creación del cliente.

Para crear el el cliente, nos creamos otro proyecto de Maven igual que hicimos con el servicio, donde vamos a cambiar el nombre (lógicamente) por "WSSUserTokenClient" y el paquete de las clases por "com.autentia.wss.usertoken.client".

Modificación del pom.xml

Igual que hicimos antes, lo primero que tenemos que hacer es modificar el fichero "pom.xml" del proyecto. En este caso vamo a realizar muchos más cambios, para poder aprovechar las distintas características de distintos plugins, entre las que debemos destacar (para el caso que nos ocupa) la generación automática de las clases clientes del servicio para ser utilizadas directamente por nuestro cliente. También crearemos las dependencias necesarias, en este caso dependecias con los distintos módulos de Rampart, para la seguridad en los servicios web.

El fichero "pom.xml" queda de la siguiente forma:

Creación de la clase cliente

Antes de nada, para poder crear nuestra clase cliente, tenemos que generar las clases clientes para acceder al servicio, esto lo hacemos ejecutando el siguiente comando de Maven la consola, situándonos en el directorio raíz de nuestro proyecto:

mvn wsdl2code:wsdl2code

El código nos lo ha generado en el directorio "target/generated-sources/axis2/wsdl2code/src", por lo que en nuestro proyecto de eclipse le debemos indicar que dicho directorio es un directorio de código fuente. Esto lo hacemos en las propiedades de nuestro proyecto.

Ahora ya podemos crear nuestra clase cliente "EchoClient.java" que tendrá el siguiente código:

Módulos de Rampart

Como podemos ver en el código fuente de la clase, vinculamos a la petición el módulo de Rampart; para que esto funcione correctamente, cuando creamos el contexto de Rampart le pasamos como parámetro el "path" del directorio padre que contiene un directorio con nombre "modules" donde se encuentran los módulos "rampart-1.4" y "rahas-1.4". En nuestro caso nos hemos creado un directorio "modules" en nuestro proyecto, donde hemos copiado dichos módulos.

Pruebas unitarias

Para comprobar que nuestro cliente funciona correctamente vamos a crearnos una clase de pruebas unitarias con JUnit para probar dicho funcionamiento. Nuestra clase de prueba la ubicaremos dentro del directorio destinado para las pruebas "src/test/java", para que luego no se incluya en el JAR que generemos.

La clase de prueba "TestEcho.java" tiene el siguiente código:

Para ejecutar los tests que hemos programado, pulsamos sobre la clase "TestEcho.java" con el botón derecho y seleccionamos "Run as --> JUnit Test", y podemos ver el resultado de la ejecución.

Empaquetando y ejecutando el cliente

Gracias a las pruebas unitarias, podemos asegurarnos que nuestro cliente está funcionando, por lo que podemos generar un JAR que se ejecute directamente; esto lo hacemos ejecutando el siguiente comando de Maven en la consola, situándonos en el directorio raíz de nuestro proyecto.

mvn package

Esto nos genera el fichero "WSSUserTokenClient-1.0-SNAPSHOT.jar" en el directorio "target" de nuestro proyecto, y también nos ha copiado todos los módulos de Rampart en en directorio "target/modules" y los JAR's de todas las dependencias en el directorio "target/lib". De esta forma, si abrimos una consola y vamos al directorio "target" de nuestro proyecto, podemos ejecutar directamente nuestro cliente con el comando:

java -jar WSSUserTokenClient-1.0-SNAPSHOT.jar

Conclusiones

Como podéis ver el módulo Rampart para Axis2 nos proporciona la implementación necesaria para WS-Security, y que combinando varias tecnologías (Axis2, Maven, Rampart, JUnit) podemos generar y probar, en este caso servicios web seguros de un modo relativamente sencillo.

Un saludo.
Borja Lázaro de Rafael.

A continuación puedes evaluarlo:

Regístrate para evaluarlo

Por favor, vota +1 o compártelo si te pareció interesante

Share |
Anímate y coméntanos lo que pienses sobre este TUTORIAL:

Fecha publicación: 2011-08-09-18:50:52

Autor: diegooooogle

No mamen, claro que funciona, solo tenia un pequeño error en la generación de las clases Java desde el WSDL pero en el comentario de bogoa666 dice cual es el comando que se debe de ejecutar en la consola del maven. Lo demás que pueda parecer error solo se soluciona con "Investigación" investiguen huevones!!!

Fecha publicación: 2011-07-28-09:14:22

Autor: blazaro

Gracias por los comentarios, los cambios que has necesitado hacer para que te funcionase seguramente se deben a que el tutorial lo hice hace más de dos años, y en este tiempo se han cambiado versiones y datos de configuración.
En cualquier caso, espero que os siga sirviendo como punto de partida.

Fecha publicación: 2011-07-27-22:07:45

Autor: eachavezv

falta una bibliotecade apache en el servidor backport-util-concurrent-3.1.jar

y listo!!!

Fecha publicación: 2011-07-26-22:40:55

Autor: eachavezv

confimado el ejemplo está MALO!!!

Fecha publicación: 2011-07-26-01:11:19

Autor: eachavezv

Excelente, eso si faltan algunos detalles como indicar que el comando de generación de código es: mvn axis2-wsdl2code:wsdl2code y no mvn wsdl2code:wsdl2code y que faltan el package bouncycastle y backport-util-concurrent para los test, pero aún así aparece el error en el header, en mi caso almenos, de todas formas hay una clase (ReadWriteLock) que me esta jodiendo.... alguna idea??

Fecha publicación: 2011-03-16-10:53:53

Autor: bogoa666

Esta muy bien y me ha ayudado mucho. Solo una puntualización al crear la clase cliente:
"mvn wsdl2code:wsdl2code" no me funcionó y usé "mvn axis2-wsdl2code:wsdl2code" que fue perfectamente.

Fecha publicación: 2010-07-21-23:37:16

Autor: ecram

El ejemplo me genera errores por problemas de configuración del POM, seria interesante tener al alcance el Código Fuente.
Saludos,
Marcelo

Fecha publicación: 2010-02-15-19:05:39

Autor: mikkel

Hola buenas. he seguido el tutorial pero a la hora de crear el paquete del servicio con mvn package (parate del servidor) me da BUILD ERROR: Internal error executing goal 'org.aache.axis2-aar-maven-plugin:1.4.1:aar' Unable to load the mojo 'org.apache.axis2-aar-maven-plugin:1.4.1:aar' in the plugin 'org.apache.axis2-aar-maven-plugin'. A required class is missing: org/apache/maven/archiver/MavenArchiveConfiguration.
Alguna sugerencia o idea, gracias de antemano.