Estoy intentando acceder a un servicio web de terceros que requiere para crear un encabezado de seguridad que transmita información de tiempo, nombre de usuario y contraseña. He buscado en la web ejemplos de trabajo y he intentado de varias maneras. Intento hacer esto con lo que está integrado en Java 6. No estoy seguro de lo que estoy haciendo mal. Después de generar mis clases de cliente del servicio web desde WSDL, creé el controlador a continuación.com.sun.xml.ws.message.saaj.SAAJHeader no se puede convertir a com.sun.xml.ws.security.opt.impl.outgoing.SecurityHeader
import java.util.Set;
import java.util.TimeZone;
import javax.xml.namespace.QName;
import javax.xml.soap.Node;
import javax.xml.soap.SOAPElement;
import javax.xml.soap.SOAPEnvelope;
import javax.xml.soap.SOAPFactory;
import javax.xml.soap.SOAPHeader;
import javax.xml.soap.SOAPMessage;
import javax.xml.soap.Text;
import javax.xml.ws.handler.MessageContext;
import javax.xml.ws.handler.soap.SOAPHandler;
import javax.xml.ws.handler.soap.SOAPMessageContext;
public class MyHeaderHandler implements SOAPHandler<SOAPMessageContext>
{
public boolean handleMessage(SOAPMessageContext context)
{
String prefixUri = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-";
String uri = prefixUri + "wssecurity-secext-1.0.xsd";
String uta = prefixUri + "wssecurity-utility-1.0.xsd";
String ta = prefixUri + "username-token-profile-1.0#PasswordText";
Boolean isRequest = (Boolean)context.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
if(isRequest)
{
try
{
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:dd.SSS'Z'");
formatter.setTimeZone(TimeZone.getTimeZone("GMT"));
java.util.Date created = new java.util.Date();
java.util.Date expires = new java.util.Date(created.getTime() + (5l * 60l * 1000l));
SOAPMessage soapMsg = context.getMessage();
SOAPEnvelope soapEnv = soapMsg.getSOAPPart().getEnvelope();
SOAPHeader soapHeader = soapEnv.getHeader();
if (soapHeader == null)
soapHeader = soapEnv.addHeader();
SOAPFactory factory = SOAPFactory.newInstance();
SOAPElement securityElem = factory.createElement("Security", "o", uri);
securityElem.addAttribute(QName.valueOf("s:mustUnderstand"), "0");
SOAPElement timestampElem = factory.createElement("Timestamp", "u", uta);
timestampElem.addAttribute(QName.valueOf("xmlns:u"), uta);
timestampElem.addAttribute(QName.valueOf("Id"), "_0");
SOAPElement elem = factory.createElement("Created", "u", uta);
elem.addTextNode(formatter.format(created));
timestampElem.addChildElement(elem);
elem = factory.createElement("Expires", "u", uta);
elem.addTextNode(formatter.format(expires));
timestampElem.addChildElement(elem);
securityElem.addChildElement(timestampElem);
SOAPElement usernameElem = factory.createElement("UsernameToken", "o", uri);
elem = factory.createElement("Username", "o", uri);
elem.addTextNode("xxxxx");
usernameElem.addChildElement(elem);
elem = factory.createElement("Password", "o", uri);
elem.addTextNode("xxxxx");
elem.addAttribute(QName.valueOf("Type"), ta);
usernameElem.addChildElement(elem);
securityElem.addChildElement(usernameElem);
soapHeader.addChildElement(securityElem);
}
catch(Exception e)
{
System.out.println("Handler error!!!! - " + e);
}
}
return true;
}
public boolean handleFault(SOAPMessageContext context)
{
return true;
}
public void close(MessageContext context)
{
}
public Set<QName> getHeaders()
{
return null;
}
}
A continuación, codifiqué mi programa de prueba para adjuntar el controlador e intentar llamar al servicio web.
import java.util.ArrayList;
import java.util.List;
import javax.xml.namespace.QName;
import javax.xml.ws.handler.Handler;
import javax.xml.ws.handler.HandlerResolver;
import javax.xml.ws.handler.PortInfo;
import org.tempuri.ServiceName;
import org.tempuri.IServiceName;
public class test
{
public static void main(String[] args)
throws Exception
{
ServiceName service = new ServiceName(new URL("https://url.to.service/services/ServiceName.svc?wsdl"), new QName("http://org.tempuri/", "ServiceName"));
service.setHandlerResolver(new HandlerResolver()
{
public List<Handler> getHandlerChain(PortInfo portInfo)
{
List<Handler> handlerList = new ArrayList<Handler>();
handlerList.add(new MyHeaderHandler());
return handlerList;
}
});
IServiceName binding = service.getBasicHttpBindingIServiceName();
ArrayLiist results = binding.getMyData("my parm");
System.out.println("Size: " + results.size());
}
}
Cuando ejecuto esto, me sale el siguiente error en la línea en la que hago binding.getMyData():
Exception in thread "main" java.lang.ClassCastException: com.sun.xml.ws.message.saaj.SAAJHeader cannot be cast to com.sun.xml.ws.security.opt.impl.outgoing.SecurityHeader
at com.sun.xml.ws.security.opt.impl.JAXBFilterProcessingContext.setJAXWSMessage(JAXBFilterProcessingContext.java:140)
at com.sun.xml.wss.jaxws.impl.SecurityPipeBase.secureOutboundMessage(SecurityPipeBase.java:389)
at com.sun.xml.wss.jaxws.impl.SecurityClientPipe.process(SecurityClientPipe.java:196)
at com.sun.xml.ws.api.pipe.helper.PipeAdapter.processRequest(PipeAdapter.java:115)
at com.sun.xml.ws.api.pipe.Fiber.__doRun(Fiber.java:595)
at com.sun.xml.ws.api.pipe.Fiber._doRun(Fiber.java:554)
at com.sun.xml.ws.api.pipe.Fiber.doRun(Fiber.java:539)
at com.sun.xml.ws.api.pipe.Fiber.runSync(Fiber.java:436)
at com.sun.xml.ws.client.Stub.process(Stub.java:248)
at com.sun.xml.ws.client.sei.SEIStub.doProcess(SEIStub.java:135)
at com.sun.xml.ws.client.sei.SyncMethodHandler.invoke(SyncMethodHandler.java:109)
at com.sun.xml.ws.client.sei.SyncMethodHandler.invoke(SyncMethodHandler.java:89)
at com.sun.xml.ws.client.sei.SEIStub.invoke(SEIStub.java:118)
at $Proxy40.getM(Unknown Source)
at test.main(test.java:30)
Cada enfoque que intento termina en el mismo punto. ¿Cómo puedo evitar esto? No puedo encontrar la manera de crear SecurityHeader para colocar en el encabezado. Cualquier ayuda sería muy apreciada. Un ejemplo de trabajo sería genial.
Gracias!