JAX-WS客户端CXF WS-Policy问题

问题描述:

我必须实现一个使用外部合作伙伴服务的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。

在此先感谢!

几天后,我发现了此问题的方法 - 不会把它的解决方案;-)

起初旧版本: 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]); 

我不知道到底为什么这种解决方法实际工作,但它确实:-) 也许你有人可以给我这样的启示。

为了安全起见CXF不处理出站端的多个策略选项,仅在入站端处理。因此,您唯一的选择是将策略收紧至Kerberos或UsernameToken,具体取决于您希望客户使用的任何策略。

+0

感谢Colm O hEigeartaigh! 有没有办法告诉客户忽略这些政策,只发送一个UsernameToken-Request? 由于服务器端由外部合作伙伴定义,因此我无法收紧策略。 –

+0

这可能会帮助你:http://cxf.apache.org/ws-policy-framework.html。默认情况下,第一个策略选择被选中,但可能有一种方法来配置它。 –

+0

Thx Colm O hEigeartaigh!我会看看它。 除此之外,我找到了一种解决方法。也许你可以给这个解决方法一些优点或缺点。 –