CXF Client Security

I am creating a client for the .net web service, but I have problems with how to pass the password correctly. Here is my hardcode 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 pass the password to the callback handler. The examples I saw in the CXF documentation implement a "hardcoded" callback (as in this example) or as a username function:

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

None of them 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); ... } 
+6
source share
3 answers

Use PW_CALLBACK_REF instead of PW_CALLBACK_CLASS and pass an instance of the object instead of a static class. You can enter a password in the specified object.

Sort of:

  outProps.put(WSHandlerConstants.PASSWORD_TYPE, WSConstants.PW_TEXT); CXFClientPasswordHandler handler = new CXFClientPasswordHandler(); handler.setPassword(password); outProps.put(WSHandlerConstants.PW_CALLBACK_REF, handler); 
+9
source

I could also 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); 
+3
source

I have always used the following method of adding properties for context request for authentication at the http level and CallbackHandler for adding a message level username token.

 org.apache.cxf.endpoint.Client client = ClientProxy.getClient(obj); org.apache.cxf.endpoint.Endpoint cxfEndpoint = client.getEndpoint(); 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> requestContext = ((BindingProvider) obj).getRequestContext(); //For message level authentication requestContext.put("ws-security.username", "Ron"); requestContext.put("ws-security.callback-handler", "com.ws.cxf.client.callback.UTPasswordCallback"); //For endpoint level authentication, HTTP Basic/Digest requestContext.put(BindingProvider.USERNAME_PROPERTY, username); requestContext.put(BindingProvider.PASSWORD_PROPERTY, password); class UTPasswordCallback implements CallbackHandler { @Override public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException { for(Callback cb:callbacks){ WSPasswordCallback pcallback = (WSPasswordCallback)cb; if(pcallback.getUsage()==WSPasswordCallback.USERNAME_TOKEN) { if(pcallback.getIdentifier().equals("Ron")) pcallback.setPassword("noR"); } } } } 
0
source

Source: https://habr.com/ru/post/892402/


All Articles