Páginas

jueves, 12 de enero de 2012

Autenticación JAX-WS UsernameToken desde cliente

En este POST se pretende mostrar como configurar un cliente JAX-WS que consuma un servicio que requiera autenticación a través de UsernameToken.

A continuación se indican las librerías necesarias para la implementación del ejemplo así como sus coordenadas para la herramienta Maven.

  • jaxb-impl
    • groupId: com.sun.xml.bind
    • artifactId: jaxb-impl
  • xws-security
    • groupId: com.sun.xml.wss
    • artifactId: xws-security
  • xmlsec
    • groupId: com.sun.org.xml.security
    • artifactId: xmlsec
  • jaxp-api
    • groupId: javax.xml
    • artifactId: jaxp-api
  • xercesImpl
    • groupId: activesoap
    • artifactId: xercesImpl
  • jaxb-xalan
    • groupId: activesoap
    • artifactId: jaxb-xalan
Acceso al servicio

 URL url = new URL("http://rutaAplicacion/nombreServicio");
 QName qname = new QName("e3swsdl-master", "nombreServicio");
NombreServicioService locator = new NombreServicioService(url, qname);
NombreServicio port = locator.getPort(NombreServicio.class);
//Manejador
final List<Handler> chain = new ArrayList<Handler>();
 chain.add(new SecurityHandler());
 ((BindingProvider) port).getBinding().setHandlerChain(chain);
 //Llamada operación del servicio
 port.metodoServicio(...);


Manejador

import java.io.IOException;
import java.io.InputStream;
import java.util.HashSet;
import java.util.Set;
import javax.xml.namespace.QName;
import javax.xml.soap.SOAPMessage;
import javax.xml.ws.handler.MessageContext;
import javax.xml.ws.handler.soap.SOAPHandler;
import javax.xml.ws.handler.soap.SOAPMessageContext;
import com.sun.xml.wss.ProcessingContext;
import com.sun.xml.wss.XWSSProcessor;
import com.sun.xml.wss.XWSSProcessorFactory;
import com.sun.xml.wss.XWSSecurityException;

public class SecurityHandler implements SOAPHandler<SOAPMessageContext> {

 XWSSProcessor cprocessor = null;

 public SecurityHandler() {
 //Leemos el archivo de configuración del servidor
 final InputStream input = this.getClass().getResourceAsStream("/user-pass-authenticate-client.xml");

 try {
 // inicializamos el XWSSProcessor
 final XWSSProcessorFactory factory = XWSSProcessorFactory.newInstance();
 cprocessor = factory.createProcessorForSecurityConfiguration(input, new SecurityEnvironmentHandler());
 input.close();

 } catch (final XWSSecurityException e) {
 //TODO tratar la excepción
 throw new RuntimeException(e);
 } catch (final IOException e) {
 //TODO tratar la excepción
 }

 }

 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) {
 return secureClient(messageContext);

 }

 public void close(final MessageContext messageContext) {
 }

 private boolean secureClient(final SOAPMessageContext messageContext) {
 final Boolean outMessageIndicator = (Boolean) messageContext.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
 final SOAPMessage message = messageContext.getMessage();
 boolean ok = false;
 if (outMessageIndicator.booleanValue()) {
 ProcessingContext context;
 try {
 context = cprocessor.createProcessingContext(message);
 context.setSOAPMessage(message);
 final SOAPMessage secureMsg = cprocessor.secureOutboundMessage(context);
 secureMsg.writeTo(System.out);
 messageContext.setMessage(secureMsg);
 ok = true;
 } catch (final Exception e) {
 e.printStackTrace();
 throw new RuntimeException(e);
 }
 } else {
 ok = false;
 }
 return ok;
 }
}




Seguridad

import java.io.IOException;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.UnsupportedCallbackException;
import com.sun.xml.wss.impl.callback.PasswordCallback;
import com.sun.xml.wss.impl.callback.UsernameCallback;

/**
 * Handle the WSS user/pass security.
 */
public class SecurityEnvironmentHandler implements CallbackHandler {

 public void handle(final Callback[] callbacks) throws IOException, UnsupportedCallbackException {
 for (final Callback callback : callbacks) {
 if (callback instanceof UsernameCallback) {

 final UsernameCallback cb = (UsernameCallback) callback;
 final String userName = "USUARIO";
 if (userName == null) {
 throw new IOException("La configuaricion del parametro '" + "USARIO" + "' es requerida");
 }
 cb.setUsername(userName);

 } else if (callback instanceof PasswordCallback) {
 final String pass = "CLAVE";
 if (pass == null) {
 throw new IOException("La configuaricion del parametro '" + "CLAVE" + "' es requerida");
 }

 final PasswordCallback cb = (PasswordCallback) callback;
 cb.setPassword(pass);
 }
 }
 }
}


Configuración del manejador
<xwss:SecurityConfiguration xmlns:xwss="http://java.sun.com/xml/ns/xwss/config" dumpMessages="true" >
 <xwss:UsernameToken digestPassword="false"/>
</xwss:SecurityConfiguration>

Este mágnifico ejemplo debemos agradecerlo a los compañeros del blog Xnoccio donde podemos consultar el ejemplo original haciendo clic aqui