简体   繁体   中英

WS-Security UsernameToken with Apache CXF

I have a java application that interacts with a SOAP service. I used the WSDL to generate a java client via CXF, but I need to authenticate my calls using ws-security. I am looking for a code-only way to do this, and I don't have any xml configurations. This is what I have tried:

Map ctx = ((BindingProvider)port).getRequestContext();
ctx.put("ws-security.username", "joe");
ctx.put("ws-security.password", "joespassword");
port.makeSoapCall();

But I get a parse error for invalid WS-Security header. What is the right way to do this?

In SOAP UI, I can do this easily by right-clicking the soap header, clicking "Add WSS UsernameToken", and selecting "Password Text"

You are using WS-SecurityPolicy as per the code you shared. How about using WS-Security only and sending across the usernametoken using WSS4JOutInterceptor?

Check the section " Adding the interceptors via the API " in apache cfx ws-security guide here : http://cxf.apache.org/docs/ws-security.html

This is what needs to be done as per the above apache cxf documenation above. You might only need the out interceptor path.

On the client side, you can obtain a reference to the CXF endpoint using the ClientProxy helper:

import org.apache.cxf.frontend.ClientProxy;
...

GreeterService gs = new GreeterService();
Greeter greeter = gs.getGreeterPort();
...
org.apache.cxf.endpoint.Client client = ClientProxy.getClient(greeter);
org.apache.cxf.endpoint.Endpoint cxfEndpoint = client.getEndpoint();

Now you're ready to add the interceptors:

import org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor;
import org.apache.cxf.ws.security.wss4j.WSS4JOutInterceptor;
...

Map<String,Object> inProps = new HashMap<String,Object>();
... // how to configure the properties is outlined below;

WSS4JInInterceptor wssIn = new WSS4JInInterceptor(inProps);
cxfEndpoint.getInInterceptors().add(wssIn);

Map<String,Object> outProps = new HashMap<String,Object>();
outProps.put("action", "UsernameToken Timestamp");
outProps.put("passwordType", "PasswordDigest"); //remove this line if want to use plain text password
outProps.put("user", "abcd");
outProps.put("passwordCallbackClass", "demo.wssec.client.UTPasswordCallback");

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

You will need to write password callback class (UTPasswordCallback) in the example above.

Apache cxf has a complete sample for UserName token here: http://svn.apache.org/repos/asf/cxf/trunk/distribution/src/main/release/samples/ws_security/ut/

From the above link browse to client folder (src/main/java/demo/wssec/client) for user name token and UTPasswordCallback code.

EDIT: If your wsdl expects password as plain text then just remove this line from the code: outProps.put("passwordType", "PasswordDigest");

You could take a look at the "ws-security/ut" demo that ships with CXF, this shows how to add a UsernameToken programmatically. Here is the client code:

https://github.com/apache/cxf/blob/master/distribution/src/main/release/samples/ws_security/ut/src/main/java/demo/wssec/client/Client.java

Colm.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM