Exception in thread "main" javax.xml.ws.soap.SOAPFaultException:The security token could not be authenticated or authorized
atorg.apache.cxf.jaxws.JaxWsClientProxy.invoke(JaxWsClientProxy.java:155)
at $Proxy28.getKeyValue(Unknown Source)
atcom.cxf.Client.KeyValueClient.main(KeyValueClient.java:56)
Caused by: org.apache.cxf.binding.soap.SoapFault: The securitytoken could not be authenticated or authorized
atorg.apache.cxf.binding.soap.interceptor.Soap11FaultInInterceptor.unmarshalFault(Soap11FaultInInterceptor.java:75)
atorg.apache.cxf.binding.soap.interceptor.Soap11FaultInInterceptor.handleMessage(Soap11FaultInInterceptor.java:46)
atorg.apache.cxf.binding.soap.interceptor.Soap11FaultInInterceptor.handleMessage(Soap11FaultInInterceptor.java:35)
atorg.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:271)
atorg.apache.cxf.interceptor.AbstractFaultChainInitiatorObserver.onMessage(AbstractFaultChainInitiatorObserver.java:114)
atorg.apache.cxf.binding.soap.interceptor.CheckFaultInterceptor.handleMessage(CheckFaultInterceptor.java:69)
atorg.apache.cxf.binding.soap.interceptor.CheckFaultInterceptor.handleMessage(CheckFaultInterceptor.java:34)
atorg.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:271)
atorg.apache.cxf.endpoint.ClientImpl.onMessage(ClientImpl.java:800)
atorg.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.handleResponseInternal(HTTPConduit.java:1590)
atorg.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.handleResponse(HTTPConduit.java:1488)
atorg.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.close(HTTPConduit.java:1307)
atorg.apache.cxf.io.CacheAndWriteOutputStream.postClose(CacheAndWriteOutputStream.java:50)
atorg.apache.cxf.io.CachedOutputStream.close(CachedOutputStream.java:229)
atorg.apache.cxf.transport.AbstractConduit.close(AbstractConduit.java:56)
atorg.apache.cxf.transport.http.HTTPConduit.close(HTTPConduit.java:622)
atorg.apache.cxf.interceptor.MessageSenderInterceptor$MessageSenderEndingInterceptor.handleMessage(MessageSenderInterceptor.java:62)
atorg.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:271)
atorg.apache.cxf.endpoint.ClientImpl.doInvoke(ClientImpl.java:530)
atorg.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:463)
atorg.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:366)
atorg.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:319)
atorg.apache.cxf.frontend.ClientProxy.invokeSync(ClientProxy.java:96)
atorg.apache.cxf.jaxws.JaxWsClientProxy.invoke(JaxWsClientProxy.java:133)
... 2 more
最後百度到
在server端的回調函數中獲取的password 卻一直是空,搜索了好半天,才找到(這個是MD5加密的):
WSPasswordCallback 的passwordType屬性和password屬性都爲null,你只能獲得用戶名(identifier),一般這裏的邏輯是使用這個用戶名到數據庫中查詢其密碼,然後再設置到password屬性,WSS4J 會自動比較客戶端傳來的值和你設置的這個值。你可能會問爲什麼這裏CXF不把客戶端提交的密碼傳入讓我們在ServerPasswordCallbackHandler中比較呢?這是因爲客戶端提交過來的密碼在SOAP 消息中已經被加密爲MD5的字符串,如果我們要在回調方法中作比較,那麼第一步要做的就是把服務端準備好的密碼加密爲MD5 字符串,由於MD5算法參數不同結果也會有差別,另外,這樣的工作CXF 替我們完成不是更簡單嗎?
根據上面說的,我獲取的password爲null,所以這裏就不用自己判斷密碼了,只要驗證用戶名後,在設置密碼就可以自動驗證了,代碼如下:
public class ServerPasswordCallback implements CallbackHandler{
public void handle(Callback[] callbacks) throwsIOException,
UnsupportedCallbackException{
WSPasswordCallback
pc = (WSPasswordCallback)callbacks[0];
String
pw =pc.getPassword();
String
idf =pc.getIdentifier();
System.out.println("password:"+pw);
System.out.println("identifier:"+idf);
if(idf.endsWith("admin")){
pc.setPassword("admin");
}
}
}