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 handle(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?
CXF relies on WSS4J in large part to implement WS-Security. Within your own services, WS-Security can be activated by using WS-SecurityPolicy, which provides a comprehensive and sophisticated validation of the security properties of a received message.
In Apache Camel, the Camel CXF component is the key to integrating routes with Web services. You can use the Camel CXF component to create a CXF endpoint, which can be used in either of the following ways: Consumer — (at the start of a route) represents a Web service instance, which integrates with the route.
Class WSS4JOutInterceptorProperty name for a map of action IDs ( Integer ) to action class names.
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);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With