UsernameToken en Jax-ws (1/2)

04 Jun 2010

Compartelo:Share on Facebook0Share on Google+0Tweet about this on TwitterShare on LinkedIn0

El objetivo de este artículo es mostrar como usar UsernameToken según la especificación Web Services Security UsernameToken Profile 1.0. El artículo consiera que el lector ya tiene experiencia en Jax-ws y se centra sólo en la configuración del mecanismo de seguridad para publicar y consumir servicios que requieran la identificación del solicitante con usuario y password haciendo uso de Jax-ws.

Dependencias requeridas

Aunque las dependencias necesarias están incluidas en algunos servidores de aplicaciones, si lo deseamos podemos o bien bajar la implementación de referencia directamente desde su web:

https://jax-ws-commons.dev.java.net y https://jax-ws.dev.java.net

O definir la dependencia en caso de que el proyecto sea Maven.

Definir  un nuevo manejador JAX-WS

En primer lugar indicaremos sobre la clase que implementa el WS el handlerchain.xml que define el manejador de seguridad  mediante la anotación @HandlerChain.


@HandlerChain(file = "handlerchain.xml")
@WebService(serviceName = "IcmsWSAPIService", targetNamespace = "http://www.juntadeandalucia.es/icms", name = "IcmsWSAPIClient", portName = "IcmsWSAPIPort", endpointInterface = "es.juntadeandalucia.icms.IcmsPublisherClient")
public class IcmsPublisherWSImpl implements IcmsPublisher {..}

A continuación indicaremos en el fichero handlerchain.xml el nombre de la clase que implementa en manejador de seguridad.

Implementar un manejador para WSS

Se necesitará una clase que implemente SOAPHandler que haciendo uso de XWSSProcessor se encargue de procesar los mensajes SOAP con los header WSSE. Un ejemplo de esta clase podría ser:


/**
* Web Services Security UsernameToken Profile 1.0
*
*/
public class SecurityHandler implements SOAPHandler<SOAPMessageContext> {

XWSSProcessor securityProcessor = null;

/**
* Build the Security Handler
*/
public SecurityHandler() {

try {
// Creamos el procesador SOAP para WSS
final InputStream input = this.getClass().getResourceAsStream("/user-pass-authenticate-server.xml");
final XWSSProcessorFactory factory = XWSSProcessorFactory.newInstance();
securityProcessor = factory.createProcessorForSecurityConfiguration(input, new SecurityEnvironmentHandler());
input.close();
} catch (final Exception e) {
logger.error("No se puede inicializar El Handler", e);
}

}

/**
*  Recuperamos el bloque header.
*/
public Set<QName> getHeaders() {
final QName securityHeader = new QName("http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-   secext-1.0.xsd", "Security", "wsse");
final HashSet<QName> headers = new HashSet<QName>();
headers.add(securityHeader);
return headers;
}

public boolean handleFault(final SOAPMessageContext messageContext) {
return true;
}

public boolean handleMessage(final SOAPMessageContext messageContext) {
final SOAPMessage message = messageContext.getMessage();

try {
// Contexto WSS
final ProcessingContext context = securityProcessor.createProcessingContext(message);
context.setSOAPMessage(message);
SOAPMessage verifiedMsg = null;
verifiedMsg = securityProcessor.verifyInboundMessage(context);

// Obtenemos el usuario y pass indicado en la request
String username = null;
String pass = null;
final Subject subject = SubjectAccessor.getRequesterSubject(context);

final Set<Principal> principals = subject.getPrincipals();
if (!principals.isEmpty()) {
final Principal principal = principals.iterator().next();
// Obtenemos en CN: CN=userName
username = StringUtils.substringAfterLast(principal.getName(), "=");
}
final Set<Object> publicCredentials = subject.getPublicCredentials();
if (!publicCredentials.isEmpty()) {
pass = (String) publicCredentials.iterator().next();
}

// Verificamos el comportamiento user y pass
validateUser(username, pass);

messageContext.setMessage(verifiedMsg);
} catch (final XWSSecurityException e) {
logger.error("WSS validation problem. ", e);
throw SecurableSoapMessage.newSOAPFaultException("WS validation problem.", e);
}

return true;
}

/** Validación específica de la aplicación.
* @param username
* @param pass
* @throws XWSSecurityException
*/
private void validateUser(final String username, final String pass) throws XWSSecurityException {
// Verificación específica de la aplicación.
//throw new XWSSecurityException("Invalid user." + username);

}

public void close(final MessageContext messageContext) {
}

private static Logger logger = Logger.getLogger(SecurityHandler.class);

}

Esta clase será la encargada de procesar todos los mensajes, verificando que todos son válidos y contienen un usuario y pass correcto. Un ejemplo de un mensaje válido WSS sería:


<?xml version="1.0" encoding="UTF-8"?>
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
<S:Header>
<wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"       S:mustUnderstand="1">
<wsse:UsernameToken xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="XWSSGID-1255949753848350309586">
<wsse:Username>usuario</wsse:Username>
<wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">****</wsse:Password>
<wsse:Nonce EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">9w+YwOatF9l1/otioQ75d5Yr</wsse:Nonce>
<wsu:Created>2009-10-19T10:55:54.418Z</wsu:Created>
</wsse:UsernameToken>
</wsse:Security>
</S:Header>
<S:Body>
<ns2:ping xmlns:ns2="http://www.juntadeandalucia.es/icms" xmlns:ns3="http://www.juntadeandalucia.es/icms/data">
<ns2:request>test</ns2:request>
</ns2:ping>
</S:Body>
</S:Envelope>

Próximamente cómo crear un cliente Jax-ws que consuma servicios securizados con   UsernameToken.

Post relacionados

Compartelo:Share on Facebook0Share on Google+0Tweet about this on TwitterShare on LinkedIn0

4 Respuestas to “UsernameToken en Jax-ws (1/2)”

  1. Octavio Ramirez 14 de Junio de 2010 at 21:06 #

    Muy interesante!!!, cuando viene la parte 2. Saludos

  2. Alejo 24 de Mayo de 2012 at 16:20 #

    Buena información. Qué contenido tendría el archivo handlerchain.xml?

  3. Felix G. Borrego 28 de Mayo de 2012 at 11:46 #

    Hola,
    En nuestro caso el fichero handlerchain.xml simplemente indica cual es la clase que implementa el manejador:

    <handler-chains xmlns=”http:/<!–more–>/java.sun.com/xml/ns/javaee”>
    <handler-chain>
    <handler>
    <handler-class>org.viafirma.conector.security.SecurityServiceWebHandler</handler-class>
    </handler>
    </handler-chain>
    </handler-chains>

  4. ceal 29 de Mayo de 2012 at 15:24 #

    Buen Dia, debo decir que es muy buen articulo y funciona ok.
    Mi consulta es si podrias ayudarme realizando lo mismo pero sin usar librerias de SUN y buscar como realizaria lo mismo pero utilizando librerias de IBM, lo que pasa que estoy tratando de ponerle seguridad a un web services con usernametoken pero en un entorno de IBM, estoy utilizando el WAS como servidor de aplicaciones.

Dejar un comentario

*