Per generare un client di un Web Service messo in sicurezza come visto nel precedente post occorre per prima cosa tramite l'utility wsimport (vedi qui ) generare le classi del client e dopo aggiungere l'handler che si occuperà in questo caso di scrivere username e password nell'header soap.
Ho scritto 2 classi una è l'implementazione dell'HandlerResolver usati in JAX-WS 2.0 proprio per "prendere il controllo" della eventuale catena di Handler presenti (in questo caso sarà soltanto uno).
Poi invece bisogna scrivere l'handler specifico che implementerà al solito l'interfaccia SOAPHandler.
MyHandler
WsSecurityHandler
package it.handler;
import java.io.IOException;
import java.util.Set;
import java.util.TreeSet;
import javax.xml.namespace.QName;
import javax.xml.soap.SOAPElement;
import javax.xml.soap.SOAPEnvelope;
import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPFactory;
import javax.xml.soap.SOAPHeader;
import javax.xml.ws.handler.MessageContext;
import javax.xml.ws.handler.soap.SOAPHandler;
import javax.xml.ws.handler.soap.SOAPMessageContext;
/**
* Handler che gestisce il passaggio <br>
* di username e password nell'header soap
* @author
*
*/
public class WSSecurityHandler implements SOAPHandler {
private boolean scriviOutputSuConsole=true;
/**
* INSERIRE LO USERNAME
*/
public static final String USER_NAME="pippo";
/**
* INSERIRE LA PWD
*/
public static final String PWD="pluto";
@Override
public void close(MessageContext arg0) {
if(scriviOutputSuConsole) System.out.println("CLOSE");
}
@Override
public boolean handleFault(MessageContext context1) {
SOAPMessageContext context = (SOAPMessageContext)context1;
try {
if(scriviOutputSuConsole)context.getMessage().writeTo(System.out);
} catch (SOAPException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return false;
}
@Override
public boolean handleMessage(MessageContext context1) {
SOAPMessageContext context = (SOAPMessageContext)context1;
Boolean outbound = (Boolean)context.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
if (outbound.booleanValue())
{
try {
SOAPEnvelope envelope = context.getMessage().getSOAPPart().getEnvelope();
SOAPFactory factory = SOAPFactory.newInstance();
String prefix = "wsse";
String uri = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd";
SOAPElement securityElement = factory.createElement("Security", prefix, uri);
QName nameMust = new QName(envelope.getPrefix()+":mustUnderstand");
securityElement.addAttribute(nameMust, "1");
securityElement.addNamespaceDeclaration("wsu", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd");
SOAPElement tokenElement = factory.createElement("UsernameToken", prefix, uri);
QName nameWSU = new QName("wsu:Id");
tokenElement.addAttribute(nameWSU, "token-1-1236072936329-25515818");
SOAPElement username = factory.createElement("Username", prefix, uri);
username.addTextNode(USER_NAME);
SOAPElement pwd = factory.createElement("Password", prefix, uri);
pwd.addTextNode(PWD);
tokenElement.addChildElement(username);
tokenElement.addChildElement(pwd);
securityElement.addChildElement(tokenElement);
SOAPHeader header = envelope.addHeader();
header.addChildElement(securityElement);
if(scriviOutputSuConsole) context.getMessage().writeTo(System.out);
} catch (Exception e) {
e.printStackTrace();
}
}
else
{
}
return true;
}
@Override
public Set getHeaders() {
return new TreeSet();
}
}
A questo punto dal nostro client Java dobbiamo scrivere il seguente codice (supponiamo di aver messo in sicurezza il Web Service visto in questo post )
FattorialeDaoImplService f=new FattorialeDaoImplService();
CalcoloWs port=f.getCalcoloWsPort();
HandlerResolver resolver = new MyHandler();
f.setHandlerResolver(resolver);
long fatt=port.getFattoriale(5);
System.out.println(fatt);
Ho scritto 2 classi una è l'implementazione dell'HandlerResolver usati in JAX-WS 2.0 proprio per "prendere il controllo" della eventuale catena di Handler presenti (in questo caso sarà soltanto uno).
Poi invece bisogna scrivere l'handler specifico che implementerà al solito l'interfaccia SOAPHandler.
MyHandler
import java.util.ArrayList;
import java.util.List;
import javax.xml.ws.handler.Handler;
import javax.xml.ws.handler.HandlerResolver;
import javax.xml.ws.handler.PortInfo;
import javax.xml.ws.handler.soap.SOAPHandler;
public class MyHandler implements HandlerResolver {
@Override
public List<Handler> getHandlerChain(PortInfo portInfo) {
List<Handler> handlerList = new ArrayList<Handler>();
SOAPHandler handler = new WSSecurityHandler();
handlerList.add(handler);
return handlerList;
}
}
import java.util.List;
import javax.xml.ws.handler.Handler;
import javax.xml.ws.handler.HandlerResolver;
import javax.xml.ws.handler.PortInfo;
import javax.xml.ws.handler.soap.SOAPHandler;
public class MyHandler implements HandlerResolver {
@Override
public List<Handler> getHandlerChain(PortInfo portInfo) {
List<Handler> handlerList = new ArrayList<Handler>();
SOAPHandler handler = new WSSecurityHandler();
handlerList.add(handler);
return handlerList;
}
}
WsSecurityHandler
import java.io.IOException;
import java.util.Set;
import java.util.TreeSet;
import javax.xml.namespace.QName;
import javax.xml.soap.SOAPElement;
import javax.xml.soap.SOAPEnvelope;
import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPFactory;
import javax.xml.soap.SOAPHeader;
import javax.xml.ws.handler.MessageContext;
import javax.xml.ws.handler.soap.SOAPHandler;
import javax.xml.ws.handler.soap.SOAPMessageContext;
/**
* Handler che gestisce il passaggio <br>
* di username e password nell'header soap
* @author
*
*/
public class WSSecurityHandler implements SOAPHandler {
private boolean scriviOutputSuConsole=true;
/**
* INSERIRE LO USERNAME
*/
public static final String USER_NAME="pippo";
/**
* INSERIRE LA PWD
*/
public static final String PWD="pluto";
@Override
public void close(MessageContext arg0) {
if(scriviOutputSuConsole) System.out.println("CLOSE");
}
@Override
public boolean handleFault(MessageContext context1) {
SOAPMessageContext context = (SOAPMessageContext)context1;
try {
if(scriviOutputSuConsole)context.getMessage().writeTo(System.out);
} catch (SOAPException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return false;
}
@Override
public boolean handleMessage(MessageContext context1) {
SOAPMessageContext context = (SOAPMessageContext)context1;
Boolean outbound = (Boolean)context.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
if (outbound.booleanValue())
{
try {
SOAPEnvelope envelope = context.getMessage().getSOAPPart().getEnvelope();
SOAPFactory factory = SOAPFactory.newInstance();
String prefix = "wsse";
String uri = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd";
SOAPElement securityElement = factory.createElement("Security", prefix, uri);
QName nameMust = new QName(envelope.getPrefix()+":mustUnderstand");
securityElement.addAttribute(nameMust, "1");
securityElement.addNamespaceDeclaration("wsu", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd");
SOAPElement tokenElement = factory.createElement("UsernameToken", prefix, uri);
QName nameWSU = new QName("wsu:Id");
tokenElement.addAttribute(nameWSU, "token-1-1236072936329-25515818");
SOAPElement username = factory.createElement("Username", prefix, uri);
username.addTextNode(USER_NAME);
SOAPElement pwd = factory.createElement("Password", prefix, uri);
pwd.addTextNode(PWD);
tokenElement.addChildElement(username);
tokenElement.addChildElement(pwd);
securityElement.addChildElement(tokenElement);
SOAPHeader header = envelope.addHeader();
header.addChildElement(securityElement);
if(scriviOutputSuConsole) context.getMessage().writeTo(System.out);
} catch (Exception e) {
e.printStackTrace();
}
}
else
{
}
return true;
}
@Override
public Set getHeaders() {
return new TreeSet();
}
}
A questo punto dal nostro client Java dobbiamo scrivere il seguente codice (supponiamo di aver messo in sicurezza il Web Service visto in questo post )
FattorialeDaoImplService f=new FattorialeDaoImplService();
CalcoloWs port=f.getCalcoloWsPort();
HandlerResolver resolver = new MyHandler();
f.setHandlerResolver(resolver);
long fatt=port.getFattoriale(5);
System.out.println(fatt);
Grazie, il tuo articolo mi ha risolto un po' di problemi.
RispondiEliminaUmberto