Authentication with JAX-WS SOAP header

Una de las formas más comunes de autenticación en servicios Web es a través de credenciales del tipo usuario y contraseña, agregados como cabeceras en una solicitud SOAP. En este artículo les voy a mostrar la manera cómo enviar estos parámetros desde el cliente hacia el servidor, en donde serán recuperados para posteriormente ejecutar la lógica de autenticación requerida.

Como primer paso, se debe crear en Netbeans un proyecto Java Web para luego crear la estructura de paquetes que se muestra a continuación.


Se debe crear una Interface Notificador en donde se declarará el método que será implementado por nuestro servicio Web. En este caso, la funcionalidad a implementar será la de responder con un saludo a un nombre que se recibirá como parámetro.
package com.rolandopalermo.blog.interfaces;

import javax.jws.WebMethod;
import javax.jws.WebService;

@WebService
public interface Notificador {

    @WebMethod
    public String saludar(String nombre);
}

Como se puede apreciar, dos anotaciones fueron agregadas. La primera es @WebService y se utiliza para indicar que una clase está implementando un servicio Web o que una Service Endpoint Interface está implementando una interfaz de servicio Web. La segunda anotación, @WebMethod, indica que un método es una operación de servicio Web.

Ahora toca implementar la interfaz creada anteriormente. Dicha implementación se realizará a través de un servicio Web, tal como se muestra a continuación:



/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package com.rolandopalermo.blog.ws;

import com.rolandopalermo.blog.interfaces.Notificador;
import java.util.List;
import java.util.Map;
import javax.annotation.Resource;
import javax.jws.WebService;
import javax.xml.ws.WebServiceContext;
import javax.xml.ws.handler.MessageContext;

@WebService(serviceName = "NotificadorImpl")
public class NotificadorImpl implements Notificador {

    @Resource
    private WebServiceContext wsc;

    @Override
    public String saludar(String nombre) {
        /*Lectura de parámetros de cabecera SOAP*/
        MessageContext mc = wsc.getMessageContext();
        Map requestHeader = (Map) mc.get(MessageContext.HTTP_REQUEST_HEADERS);
        List usuarioList = (List) requestHeader.get("usuario");
        List passwrdList = (List) requestHeader.get("password");
        //***************************************************
        String usuario = "";
        String password = "";
        if (usuarioList != null && passwrdList != null) {
            usuario = (String) usuarioList.get(0);
            password = (String) passwrdList.get(0);
            if (usuario.equals("admin") && password.equals("123456")) {
                if (nombre != null && nombre.length() > 0) {
                    return "Hola " + nombre;
                }
                return "Error";
            } else {
                return "Error de autenticación";
            }
        } else {
            return "Se requiere campos de autenticación";
        }
    }
}
El último paso que resta, en el lado del servidor, sería el despliegue del proyecto. Para esto, hacer lo siguiente:


Y para finalizar, sólo resta escribir el código correspondiente a los clientes. Para el caso de Netbeans, se tendría que crear un servicio Web cliente con el WSDL del servicio Web. Si no enviamos los parámetros de autenticación, la respuesta del servicio será la siguiente:


Por otra parte, si enviamos los parámetros requeridos, tal como se muesta a continuación, la respuesta debe ser la correspondiente a un usuario correctamente autenticado.
package com.rolandopalermo.blog.cliente;

import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.xml.ws.BindingProvider;
import javax.xml.ws.handler.MessageContext;

public class Main {
    
    private static final String WS_URL = "http://localhost:8080/SOAPAuthentication/NotificadorImpl?wsdl";
    
    public static void main(String[] args) {
        
        com.rolandopalermo.blog.ws.NotificadorImpl_Service service = new com.rolandopalermo.blog.ws.NotificadorImpl_Service();
        com.rolandopalermo.blog.ws.NotificadorImpl port = service.getNotificadorImplPort();
        
        Map<String, Object> req_ctx = ((BindingProvider)port).getRequestContext();
        req_ctx.put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, WS_URL);

        Map<String, List<String>> headers = new HashMap<String, List<String>>();
        headers.put("usuario", Collections.singletonList("admin"));
        headers.put("password", Collections.singletonList("123456"));
        req_ctx.put(MessageContext.HTTP_REQUEST_HEADERS, headers);
        
        System.out.println(port.saludar("Rolando"));
        
    }
}

Al ejecutar dicho código, la respuesta será la siguiente:


Código fuente del proyecto:


Espero que este post les sea de utilidad. Cualquier consulta, no duden de escribirla en la caja de comentarios, saludos!

Comentarios