Web Service con Maven + Axis2 + Spring framework - Parte II (Seguridad)


Ya vimos en la Parte I de este tutorial cómo crear un servicio web con Maven, Axis2 y Spring. En esta segunda parte veremos cómo agregarle seguridad mediante usuario y password.

Lo primero que vamos a hacer es crear el proyecto  de nuevo siguiendo los pasos de la parte I del tutorial o bien descargamos el proyecto completo aquí.

Para implementar la seguridad haremos uso de un módulo de Axis2 llamado Rampart. Lo primero que vamos ha hacer es descargar la distribución en ZIP de dicho módulo a través de la página de módulos de Axis:
  • http://ws.apache.org/axis2/modules/ 
Si el enlace de descarga no funciona, podemos descargar las últimas versiones desde el mirror de redIris:
  • http://apache.rediris.es/ws/rampart/
Una vez descargada la distribución binaria, la descomprimimos en un directorio a nuestra elección  y copiamos el fichero situado en modules/rampart-1.x.mar en el directorio "src/main/webapp/WEB-INF/modules/" (creamos la carpeta modules si no existe).

Ahora vamos a añadir la dependencia de la librería rampart al fichero pom.xml:
<dependency>
    <groupId>org.apache.rampart</groupId>
    <artifactId>rampart-core</artifactId>
    <version>1.4</version>
</dependency>
Lo siguiente es crear una clase Java que se encargará de autenticar al usuario.
package org.tutorialexception.ws.security;

import java.io.IOException;

import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.UnsupportedCallbackException;

import org.apache.ws.security.WSPasswordCallback;

public class AuthenticationHandler implements CallbackHandler {

    public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
        if (callbacks.length > 0) {
            //Autenticación del usuario y contraseña
            WSPasswordCallback pwcb = (WSPasswordCallback)callbacks[0];
            //comprobaciones de usuario y contraseña para acceso al servicio
            if(pwcb.getIdentifer().equals("tutorialquot;) && pwcb.getPassword().equals("exception")) {
                //autenticación con éxito
                return;
            } else {
                throw new UnsupportedCallbackException(callbacks[0], "fallo de autenticación");
            }
        }
    }

}
Como puede observarse la implementación es muy sencilla y permite una personalización completa. En la línea 18, podemos recuperar el usuario y password mediante los métodos getIdentifer() y getPassword() del objeto WSPasswordCallback. Por tanto, aquí podríamos consultar un fichero, una base de datos o cualquier otra fuente de datos para comprobar que el usuario y contraseña son correctos. Si lo son, el método termina. Por el contrario, si no son correctos, lanzamos la excepción.

Ahora vamos a configurar el servicio para que haga uso de la seguridad de Rampart y delegue el trabajo de autenticación en nuestra clase. Para ello, abrimos el fichero src/main/webapp/WEB-INF/services/SaludaService/META-INF/services.xml y añadimos lo siguiente al elemento <service>:
<module ref="rampart" />

<wsp:Policy wsu:Id="UserToken"
    xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
    xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy">
    <wsp:ExactlyOne>
        <wsp:All>
            <sp:SignedSupportingTokens
                xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy">
                <wsp:Policy>
                    <sp:UsernameToken
                        sp:IncludeToken="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy/IncludeToken/AlwaysToRecipient" />
                </wsp:Policy>
            </sp:SignedSupportingTokens>
            <ramp:RampartConfig
                xmlns:ramp="http://ws.apache.org/rampart/policy">
                <ramp:passwordCallbackClass>org.tutorialexception.ws.security.AuthenticationHandler</ramp:passwordCallbackClass>
            </ramp:RampartConfig>
        </wsp:All>
    </wsp:ExactlyOne>
</wsp:Policy>
Una vez creado y configurado todo sólo nos queda probar el servicio web con la autenticación. Para ello usaremos SoapUI, tal y como se vio en la primera parte del tutorial, añadiendo la misma URL: http://localhost:8080/servicioWeb/services/SaludaService?wsdl y soapUI generará peticiones para nuestras operaciones y para los binding disponibles.

Abrimos la operación haciendo doble click sobre "Request 1":



Luego pulsamos sobre "Aut", en la esquina inferior derecha de la ventana de operación:



Nos aparecerán varios campos de los que rellenaremos únicamente "Username" y "Password". En primer lugar probaremos con un usuario y/o contraseña incorrecta:



Ahora pulsamos con el botón derecho sobre el elemento <soapenv:Header> y elegimos la opción "Add WSS Username Token" lo que nos generará una cabecera estándar de WSS con el usuario y password elegidos anteriormente. Se nos abrirá una ventana emergente preguntándonos el tipo de password, en nuestro caso nos basta con "PasswordText" que indica que la contraseña irá en texto plano.





Si lanzamos la petición, veremos que en la respuesta obtendremos una no autorización



Ahora vamos a probar con un usuario y contraseña correcta. Lo primero es eliminar los elementos dentro de <soapenv:Header>, pulsar sobre "Aut" e insertar el usuario y contraseña correcta (la aceptada por nuestra clase AuthenticationHandler).


De la misma forma que antes (botón derecho sobre <soapenv:Header>) añadimos el token de usuario



Y al probarlo veremos que todo es correcto



Puedes descargar el código fuente del proyecto aquí

1 comentarios:

Eduardo G. dijo...

Hola, una pregunta
ya hice mi autenticación y pero posteriormente necesito saber el username
ya en mi método de negocio,
cómo puedo hacerle para volver a obtener el username ya fuera de la clase del callback??

Publicar un comentario