Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CXF Client Security

I am creating a client to a Java soap web service, but am having trouble figuring out how to properly pass the password. Here is my "hardcoded" password example:

@Test
public void exploratorySecurityTest() {
     String username = "user";
     String password = "pwd";

    UserStoryService service = new UserStoryService();
    UserStoryServiceSoap port = service.getUserStoryServiceSoap();

    //initialize security
    org.apache.cxf.endpoint.Client client = ClientProxy.getClient(port); 
    org.apache.cxf.endpoint.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, ClientPasswordCallback.class.getName());
    WSS4JOutInterceptor wssOut = new WSS4JOutInterceptor(outProps);
    cxfEndpoint.getOutInterceptors().add(wssOut);

    int storyId = 33401;
    UserStoryDTO userStoryDTO = port.getByID(storyId);

    //success if no error
}

public class ClientPasswordCallback implements CallbackHandler {

@Override
public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
    WSPasswordCallback pc = (WSPasswordCallback) callbacks[0];
    pc.setPassword("pwd");
}}

What I really want to do is to pass the password into the callback handler. The examples that I have seen in the CXF documentation implement the callback either "hardcoded" (as I did in this example) or as a function of the username:

if (pc.getIdentifier().equals("user"))
   pc.setPassword("pwd");

Neither of these meet my needs. Is there a way that I can do something like the following:

@Test
public void exploratorySecurityTest() {
     String username = "user";
     String password = "pwd";

    UserStoryService service = new UserStoryService();
    UserStoryServiceSoap port = service.getUserStoryServiceSoap();

    //initialize security
    org.apache.cxf.endpoint.Client client = ClientProxy.getClient(port); 
    org.apache.cxf.endpoint.Endpoint cxfEndpoint = client.getEndpoint();
    Map<String, Object> outProps = new HashMap<String, Object>();
    outProps.put(WSHandlerConstants.ACTION, WSHandlerConstants.USERNAME_TOKEN);
    outProps.put(WSHandlerConstants.USER, username);

            //pass the password here?
            outProps.put("password", password);

    outProps.put(WSHandlerConstants.PASSWORD_TYPE, WSConstants.PW_TEXT);
    outProps.put(WSHandlerConstants.PW_CALLBACK_CLASS, ClientPasswordCallback.class.getName());
    WSS4JOutInterceptor wssOut = new WSS4JOutInterceptor(outProps);

    cxfEndpoint.getOutInterceptors().add(wssOut);
            // ...
}
like image 740
jayraynet Avatar asked Jul 09 '11 17:07

jayraynet


People also ask

What does Apache CXF use for integration with WSS4J and security?

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.

What does Apache CXF stand for?

Apache CXF is the product of two projects, Celtix and XFire , hence the name CXF . Celtix , an open source Java-based Enterprise Service Bus (ESB) project, is a product of ObjectWeb consortia that delivers open source middleware solutions.

What is the difference between Apache CXF and Axis2?

The main differences between axis2 web service and CXF web service are as follows: CXF has support for WS-Addressing, WS-Policy, WS-RM, WS-Security, and WS-I BasicProfile. Axis2 supports each of these except for WS-Policy, which will be supported in an upcoming version.

What is CXF used for?

CXF helps you build and develop services using frontend programming APIs, like JAX-WS and JAX-RS. These services can speak a variety of protocols such as SOAP, XML/HTTP, RESTful HTTP, or CORBA and work over a variety of transports such as HTTP, JMS or JBI.


2 Answers

Use PW_CALLBACK_REF instead PW_CALLBACK_CLASS, and pass an instantiated object, instead of the static class. You can inject the password in said object.

Something like:

    outProps.put(WSHandlerConstants.PASSWORD_TYPE, WSConstants.PW_TEXT);
    CXFClientPasswordHandler handler = new CXFClientPasswordHandler();
    handler.setPassword(password);
    outProps.put(WSHandlerConstants.PW_CALLBACK_REF, handler);
like image 125
Santiago Árraga Avatar answered Oct 21 '22 10:10

Santiago Árraga


I was also able to do the following:

    org.apache.cxf.endpoint.Client client = ClientProxy.getClient(obj);
    org.apache.cxf.endpoint.Endpoint cxfEndpoint = client.getEndpoint();

    Map<String, Object> outProps = new HashMap<String, Object>();

    outProps.put(WSHandlerConstants.ACTION, WSHandlerConstants.USERNAME_TOKEN);

    System.out.println("initialize security for user " + this.username);
    outProps.put(WSHandlerConstants.USER, this.username);
    outProps.put(WSHandlerConstants.PASSWORD_TYPE, WSConstants.PW_TEXT);

    Map<String, Object> ctx = ((BindingProvider) obj).getRequestContext();
    ctx.put("password", this.password);

    WSS4JOutInterceptor wssOut = new WSS4JOutInterceptor(outProps);
    cxfEndpoint.getOutInterceptors().add(wssOut);
like image 23
jayraynet Avatar answered Oct 21 '22 10:10

jayraynet