2012-01-12 93 views
5

我試圖訪問需要第三方Web服務我創建一個傳遞時間信息,用戶名和密碼的安全頭。我在網上搜索了一些工作示例,並嘗試了很多方法。我試圖用Java 6內置的內容來做到這一點。我不確定我做錯了什麼。在從WSDL生成我的Web服務客戶端類後,我在下面創建了Handler。com.sun.xml.ws.message.saaj.SAAJHeader無法轉換爲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; 
    } 
} 

接下來,我編寫我的測試程序來附加處理程序並嘗試調用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()); 
} 
} 

當我運行它,我得到以下錯誤在那裏我做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) 

每一個方法,我嘗試在相同的點結束。我如何解決這個問題?我無法弄清楚如何創建SecurityHeader放置到標題中。任何幫助將不勝感激。一個可行的例子會很棒。

謝謝!

回答

1

當我解決類似問題時,this thread really幫助了我。

問題是當你在類路徑上有Metro(Oracle的WS棧)庫時,它們被自動檢測幷包含在WS處理中。當WSDL中存在端點策略時,一種功能是透明認證/安全處理。不幸的是,這種安全處理不是

我無法更改WSDL。 我的解決方案是從類路徑中刪除不需要的JAR(wsit-rt)。

0

老問題,但我目前有同樣的問題。 解決方案是移除手動包含的其他安全性頭文件。 因此,如果遇到此問題,請檢查是否有任何處理程序(SOAPHandler)將任何標題寫入您的肥皂消息<Security>標題部分。

相關問題