2017-02-23 119 views
0

我必須實現一個使用外部合作伙伴服務的JAX-WS-Client。我使用Apache CXF。該服務在wsdl中定義了兩個用於身份驗證的WS-Policies - KerberosToken和UsernameToken。由於該服務來自外部合作伙伴,因此無法更改。JAX-WS客戶端CXF WS-Policy問題

問題:身份驗證在Kerberos身份驗證失敗,因爲我想使用 簡單的UsernameToken身份驗證。

WSLD-政策部分:CXF端點的

<wsp:Policy xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy" 
    xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" 
    wsu:Id="SecurityServiceUsernameUnsecureTransportPolicy"> 
    <wsp:ExactlyOne> 
    <wsp:All> 
    <sp:SupportingTokens xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702"> 
    <wsp:Policy> 
     <sp:KerberosToken sp:IncludeToken="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702/IncludeToken/AlwaysToRecipient"> 
     <wsp:Policy> 
     <sp:WssGssKerberosV5ApReqToken11/> 
     </wsp:Policy> 
     </sp:KerberosToken> 
    </wsp:Policy> 
    </sp:SupportingTokens> 
    </wsp:All> 
    <wsp:All> 
    <sp:SupportingTokens xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702"> 
    <wsp:Policy> 
     <sp:UsernameToken sp:IncludeToken="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702/IncludeToken/AlwaysToRecipient"> 
     <wsp:Policy> 
     <sp:WssUsernameToken10/> 
     </wsp:Policy> 
     </sp:UsernameToken> 
    </wsp:Policy> 
    </sp:SupportingTokens> 
    </wsp:All> 
    </wsp:ExactlyOne> 
</wsp:Policy> 

設置用戶名/密碼:

public void addAuthenticationProperties(Endpoint endpoint) { 
    endpoint.put(SecurityConstants.USERNAME, userName); 
    endpoint.put(SecurityConstants.PASSWORD, password); 
} 

據我瞭解-Tag意味着,如果有的話(excatly一個)的本政策正在滿載轉移。但是CXF甚至沒有嘗試填充UsernameToken - Policy。

如果我刪除-Block for KerberosToken身份驗證正常工作,但在生產中這是不可能的。

任何提示?如果在wsdl或我的方法中有錯誤,請告訴我。請詳細說明 - 我是這個領域的noob。

在此先感謝!

回答

0

幾天後,我發現了此問題的方法 - 不會把它的解決方案;-)

起初舊版本: CXF生成的類ExampleWS_Service和相應的接口ExampleWS。所以我用了ExampleWS_Service設置寄託都並調用該服務:

// creating Port 
URL url = new URL(config.getSchema(), config.getHost(), config.getPort(), config.getPath()); 

ExampleWS_Service service = new ExampleWS_Service(url); 
ExampleWS port = service.getExampleWSPort(); 

// Adding authentication-info 
Client client = ClientProxy.getClient(port); 
Endpoint cxfEndpoint = client.getEndpoint(); 

cxfEndpoint.put(SecurityConstants.USERNAME, userName); 
cxfEndpoint.put(SecurityConstants.PASSWORD, password); 

... 
// invoke service 
port.doSomething([data]); 

解決方法: 我切換到JaxWsProxyFactoryBean和設置寄託都起來。在這種情況下,需要WSS4JOutInterceptor將認證信息放入請求頭中。有些代碼:

URL url = new URL(config.getSchema(), config.getHost(), config.getPort(), config.getPath()); 

JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean(); 
factory.setServiceClass(ExampleWS.class); 
factory.setAddress(url.toString()); 
factory.setBindingId("http://schemas.xmlsoap.org/wsdl/soap12/"); 

ExampleWS port = (ExampleWS)factory.create(); 

// Adding authentication-info using WSS4JOutInterceptor 
Client client = ClientProxy.getClient(port); 
Endpoint cxfEndpoint = client.getEndpoint(); 

Map<String, Object> outProps = new HashMap<>(); 
outProps.put(WSHandlerConstants.ACTION, WSHandlerConstants.USERNAME_TOKEN); 
outProps.put(WSHandlerConstants.USER, userName); 
outProps.put(WSHandlerConstants.PASSWORD_TYPE, passwordType); 
outProps.put(WSHandlerConstants.PW_CALLBACK_REF, [Instance of javax.security.auth.callback.CallbackHandler]); 

WSS4JOutInterceptor wssOut = new WSS4JOutInterceptor(outProps); 
cxfEndpoint.getOutInterceptors().add(wssOut); 

... 
// invoke service 
port.doSomething([data]); 

我不知道到底爲什麼這種解決方法實際工作,但它確實:-) 也許你有人可以給我這樣的啓示。

0

爲了安全起見CXF不處理出站端的多個策略選項,僅在入站端處理。因此,您唯一的選擇是將策略收緊至Kerberos或UsernameToken,具體取決於您希望客戶使用的任何策略。

+0

感謝Colm O hEigeartaigh! 有沒有辦法告訴客戶忽略這些政策,只發送一個UsernameToken-Request? 由於服務器端由外部合作伙伴定義,因此我無法收緊策略。 –

+0

這可能會幫助你:http://cxf.apache.org/ws-policy-framework.html。默認情況下,第一個策略選擇被選中,但可能有一種方法來配置它。 –

+0

Thx Colm O hEigeartaigh!我會看看它。 除此之外,我找到了一種解決方法。也許你可以給這個解決方法一些優點或缺點。 –