Apache CXF - credentials not being sent from WSS4JOutInterceptor?
I am trying to connect to a web service using WS-Security UsernameToken spec 1.0, using apache cxf 2.4.0.
I've copied the code below from the CXF docs, but am getting: org.apache.cxf.ws.policy.PolicyException: No username available
MyService_Service ss = new MyService_Service(wsdlURL, SERVICE_NAME);
MyService port = ss.getBasicHttpBindingMyService ();
Client client = ClientProxy.getClient(port);
Endpoint cxfEndpoint = client.getEndpoint();
Map<String,Object> outProps = new HashMap<String,Object>();
outProps.put(WSHandlerConstants.ACTION, WSHandlerConstants.USERNAME_TOKEN);
outProps.put(WSHandlerConstants.USER, "USERNAME");
outProps.put(WSHandlerConstants.PASSWORD_TYPE, WSConstants.PW_TEXT);
outProps.put(WSHandlerConstants.PW_CALLBACK_CLASS,
ClientPasswordHandler.class.getName());
WSS4JOutInterceptor wssOut = new WSS4JOutInterceptor(outProps);
cxfEndpoint.getOutInterceptors().add(wssOut);
I've also implemented a ClientPasswordHandler class, again from the docs, but it seems like the username is never sent (according to the error). Here is the password handler:
public class ClientPasswordHandler implements CallbackHandler {
public void hand开发者_高级运维le(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
WSPasswordCallback pc = (WSPasswordCallback) callbacks[0];
pc.setPassword("Password");
}
}
Is there any way to see if the WSS4Jinterceptor is being applied, and the UsernameToken is sent?
Are you getting the PolicyException on the client side? If so, that likely means the WSDL you are using has a WS-SecucurityPolicy fragment in it that describes the UsernameToken policy that it wants and is expecting. If that's the case, then you shouldn't configure the WSS4JOutInterceptor at all. The WS-Policy runtime will handle it and you just need to provide some properties that it may need.
The docs for the SecurityPolicy stuff are at: http://cxf.apache.org/docs/ws-securitypolicy.html
You likely just need to use:
Map ctx = ((BindingProvider)port).getRequestContext();
ctx.put("ws-security.username", "USERNAME");
ctx.put("ws-security.password", "Password");
Thanks to Daniel the full working configuration for me is the following:
webServicePort = webService_service.getPort(WebService.class);
Client client = ClientProxy.getClient(webServicePort);
Endpoint cxfEndpoint = client.getEndpoint();
Map<String, Object> props = ((BindingProvider) webServicePort).getRequestContext();
props.put("ws-security.username", PravoRuConstants.USERNAME);
props.put("ws-security.password", PravoRuConstants.PASSWORD);
props.put(WSHandlerConstants.ACTION, WSHandlerConstants.USERNAME_TOKEN);
props.put(WSHandlerConstants.USER, PravoRuConstants.USERNAME);
props.put(WSHandlerConstants.PASSWORD_TYPE, WSConstants.PW_TEXT);
props.put(WSHandlerConstants.PW_CALLBACK_CLASS, PravoRuPasswordHandler.class.getName());
WSS4JOutInterceptor wssOut = new WSS4JOutInterceptor(props);
cxfEndpoint.getOutInterceptors().add(wssOut);
On using the answer from Daniel, I was getting the following exception
Caused by: org.apache.cxf.transport.http.HTTPException: HTTP response '401: Unauthorized' when communicating with http://..
at .apache.cxf.inorg.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.handleResponseInternal(HTTPConduit.java:1555)
at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.handleResponse(HTTPConduit.java:1494)
at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.close(HTTPConduit.java:1402)
at org.apache.cxf.transport.AbstractConduit.close(AbstractConduit.java:56)
at org.apache.cxf.transport.http.HTTPConduit.close(HTTPConduit.java:649)
at orgterceptor.MessageSenderInterceptor$MessageSenderEndingInterceptor.handleMessage(MessageSenderInterceptor.java:62)
at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:263)
at org.apache.cxf.endpoint.ClientImpl.doInvoke(ClientImpl.java:535)
at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:465)
at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:368)
I used the below and it started working
Map ctx = ((BindingProvider) ssPort).getRequestContext();
ctx.put(BindingProvider.USERNAME_PROPERTY, "user");
ctx.put(BindingProvider.PASSWORD_PROPERTY, "pass");
ctx.put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, "http://c
精彩评论