Sto tentando di accedere a un servizio Web di terzi che richiede per creare un'intestazione di sicurezza che trasmetta informazioni temporali, nome utente e password. Ho setacciato il web per esempi di lavoro e ho provato numerosi modi. Sto cercando di farlo con ciò che è integrato in Java 6. Non sono sicuro di cosa sto facendo male. Dopo aver generato le mie classi client del servizio Web dal WSDL, ho creato il Gestore di seguito.com.sun.xml.ws.message.saaj.SAAJHeader non può essere lanciato su 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;
}
}
Poi, ho codificato il mio programma di test per fissare il conduttore e provare a chiamare il servizio 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());
}
}
Quando eseguo questo, ottengo il seguente errore sulla linea di cui faccio 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)
Ogni approccio cerco finisce nello stesso punto. Come faccio a evitare questo? Non riesco a capire come creare SecurityHeader da inserire nell'intestazione. Qualsiasi aiuto sarebbe molto apprezzato. Un esempio funzionante sarebbe fantastico.
Grazie!