JAX-WS 客户端 CXF WS-Policy 问题
JAX-WS Client CXF WS-Policy Issue
我必须实现一个 JAX-WS-Client,它使用来自外部合作伙伴的服务。我使用 Apache CXF。该服务在 wsdl 中定义了两个用于身份验证的 WS-Policies - KerberosToken 和 UsernameToken。由于该服务来自外部合作伙伴,因此无法更改。
问题:Kerberos-Authentication 的身份验证失败,因为我想使用
简单的 UsernameToken-Authentication.
WSLD 策略部分:
<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>
在 CXF 端点设置 Username/Password:
public void addAuthenticationProperties( Endpoint endpoint ) {
endpoint.put( SecurityConstants.USERNAME, userName );
endpoint.put( SecurityConstants.PASSWORD, password );
}
据我所知,-Tag 意味着,如果此政策中的任何一个(特别是一个)已完成,请继续。但是 CXF 甚至没有尝试填写 UsernameToken - Policy。
如果我删除 KerberosToken 身份验证的 -Block 工作正常,但在生产中这是不可能的。
有什么提示吗?如果 wsdl 或我的方法有错误,请告诉我。请详细说明 - 我是这个领域的菜鸟。
提前致谢!
CXF 不处理出站端的多个策略选项以确保安全,仅在入站端处理。因此,您唯一的选择是将策略收紧到 Kerberos 或 UsernameToken,具体取决于您希望客户端使用的策略。
几天后,我找到了解决此问题的方法 - 不会称之为解决方案 ;-)
首先是旧版本:
CXF生成了一个classExampleWS_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 将身份验证信息放入 request-header。一些代码:
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] );
我不知道为什么这个解决方法确实有效,但确实有效:-)
或许你们中有人能给我这样的启示。
我必须实现一个 JAX-WS-Client,它使用来自外部合作伙伴的服务。我使用 Apache CXF。该服务在 wsdl 中定义了两个用于身份验证的 WS-Policies - KerberosToken 和 UsernameToken。由于该服务来自外部合作伙伴,因此无法更改。
问题:Kerberos-Authentication 的身份验证失败,因为我想使用 简单的 UsernameToken-Authentication.
WSLD 策略部分:
<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>
在 CXF 端点设置 Username/Password:
public void addAuthenticationProperties( Endpoint endpoint ) {
endpoint.put( SecurityConstants.USERNAME, userName );
endpoint.put( SecurityConstants.PASSWORD, password );
}
据我所知,-Tag 意味着,如果此政策中的任何一个(特别是一个)已完成,请继续。但是 CXF 甚至没有尝试填写 UsernameToken - Policy。
如果我删除 KerberosToken 身份验证的 -Block 工作正常,但在生产中这是不可能的。
有什么提示吗?如果 wsdl 或我的方法有错误,请告诉我。请详细说明 - 我是这个领域的菜鸟。
提前致谢!
CXF 不处理出站端的多个策略选项以确保安全,仅在入站端处理。因此,您唯一的选择是将策略收紧到 Kerberos 或 UsernameToken,具体取决于您希望客户端使用的策略。
几天后,我找到了解决此问题的方法 - 不会称之为解决方案 ;-)
首先是旧版本:
CXF生成了一个classExampleWS_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 将身份验证信息放入 request-header。一些代码:
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] );
我不知道为什么这个解决方法确实有效,但确实有效:-) 或许你们中有人能给我这样的启示。