On Jul 17, 2008, at 12:40 AM, Glen Mazza wrote:


If you're using CXF 2.1+, be sure *not* to add the SAAJ handlers as you're
doing below.  That's only a 2.0.x thing.


Actually, it's not a big deal if you do add them. It's smart enough to check if its needed or not.

Dan


Also, you *might* be able to use more Spring configuration and pull out more of that coding, in particular the WSS4JInInterceptor--storing the username
might be troublesome though:
http://cwiki.apache.org/CXF20DOC/ws-security.html#WS-Security-SpringXMLConfiguration

BTW, I just finished my blog entry on this. Our code is similar, but maybe
you can find something else to leverage:
http://www.jroller.com/gmazza/date/20080716

Glen


Gary Weaver wrote:

Just verified that it works to set PW_CALLBACK_REF instead of
PW_CALLBACK_CLASS.

Do you think it would help to have examples on
http://cwiki.apache.org/CXF20DOC/ws-security.html that use
WSHandlerConstants.PW_CALLBACK_REF in addition (or maybe instead?) of
those that use WSHandlerConstants.PW_CALLBACK_CLASS?

This seems like it might be a good idea, since it would probably
increase CXF performance at little to reduce instantiation of a
CallbackHandler via reflection on every call.

HTH,
Gary


Gary Weaver wrote:
The first thing I should have done is to look at the WSS4J source... ;)

The code in WSS4J 1.5.4 to get your CallbackHandler is (
http://svn.apache.org/viewvc/webservices/wss4j/tags/1_5_4/src/org/apache/ws/security/handler/WSHandler.java?view=markup
):

--- start code ---
  /**
   * Get the password callback class and get an instance
   * <p/>
   */
  protected CallbackHandler getPasswordCB(RequestData reqData)
  throws WSSecurityException {

  Object mc = reqData.getMsgContext();
      CallbackHandler cbHandler = null;
      String callback =
getString(WSHandlerConstants.PW_CALLBACK_CLASS, mc);
      if (callback != null) {
          Class cbClass = null;
          try {
              cbClass = Loader.loadClass(getClassLoader(reqData
                      .getMsgContext()), callback);
          } catch (ClassNotFoundException e) {
              throw new WSSecurityException(
"WSHandler: cannot load password callback class: "
             + callback, e);
          }
          try {
              cbHandler = (CallbackHandler) cbClass.newInstance();
          } catch (java.lang.Exception e) {
              throw new WSSecurityException(
                   "WSHandler: cannot create instance of password
callback: "
           + callback, e);
          }
      } else {
          cbHandler = (CallbackHandler) getProperty(mc,
                         WSHandlerConstants.PW_CALLBACK_REF);
          if (cbHandler == null) {
              throw new WSSecurityException(
                         "WSHandler: no reference in callback
property");
          }
      }
      return cbHandler;
  }
--- end code ---

So it looks like setting the instance of your CallbackHandler is as
easy as setting:

MyCallbackHandler myCallbackHander = new MyCallbackHandler();
myCallbackHander.setPassword(password);
outProps.put(WSHandlerConstants.PW_CALLBACK_REF, myCallbackHander);

:) !

Here are the revised files:

--- start example code MyClient.java ---

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.cxf.binding.soap.saaj.SAAJInInterceptor;
import org.apache.cxf.binding.soap.saaj.SAAJOutInterceptor;
import org.apache.cxf.endpoint.Client;
import org.apache.cxf.endpoint.Endpoint;
import org.apache.cxf.frontend.ClientProxy;
import org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor;
import org.apache.cxf.ws.security.wss4j.WSS4JOutInterceptor;
import org.apache.ws.security.WSConstants;
import org.apache.ws.security.handler.WSHandlerConstants;

import java.util.HashMap;
import java.util.Map;


public class MyClient {

 private String endpoint;
 private String user;
 private String password;

 private Log log = LogFactory.getLog(MyClient.class);

 protected void testService() {

     MyService service = new MyService(null);
     MyServicePortType portType = service.getMyServicePort();
     Client client = ClientProxy.getClient(portType);

     // set username and password
     // see: http://cwiki.apache.org/CXF20DOC/ws-security.html
     Endpoint clientEndpoint = client.getEndpoint();
     // No security on client-side
     Map<String, Object> inProps = new HashMap<String, Object>();
     inProps.put(WSHandlerConstants.ACTION,
WSHandlerConstants.NO_SECURITY);
     WSS4JInInterceptor wssIn = new WSS4JInInterceptor(inProps);
     clientEndpoint.getInInterceptors().add(wssIn);
clientEndpoint.getInInterceptors().add(new SAAJInInterceptor());
// 2.0.x only; not needed in 2.1+
     // Server-side authN
     Map<String, Object> outProps = new HashMap<String, Object>();
     outProps.put(WSHandlerConstants.ACTION,
WSHandlerConstants.USERNAME_TOKEN);
     outProps.put(WSHandlerConstants.USER, getUser());
     outProps.put(WSHandlerConstants.PASSWORD_TYPE,
WSConstants.PW_TEXT);
     //outProps.put(WSHandlerConstants.PASSWORD_TYPE,
WSConstants.PW_DIGEST);
MyCallbackHandler myCallbackHander = new MyCallbackHandler();
     myCallbackHander.setPassword(password);
outProps.put(WSHandlerConstants.PW_CALLBACK_REF, myCallbackHander);

     WSS4JOutInterceptor wssOut = new WSS4JOutInterceptor(outProps);
     clientEndpoint.getOutInterceptors().add(wssOut);
     clientEndpoint.getOutInterceptors().add(new
SAAJOutInterceptor()); // 2.0.x only; not needed in 2.1+

     MyServiceResponse response =
portType.someServiceMethod(MyServiceRequest);
     return response;
 }

 public String getEndpoint() {
     return endpoint;
 }

 public void setEndpoint(String endpoint) {
     this.endpoint = endpoint;
 }

 public String getUser() {
     return user;
 }

 public void setUser(String user) {
     this.user = user;
 }

 public String getPassword() {
     return password;
 }

 public void setPassword(String password) {
     this.password = password;
 }
}

--- end example code MyClient.java ---

--- start example code MyCallbackHandler.java ---

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.ws.security.WSPasswordCallback;

import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.UnsupportedCallbackException;
import java.io.IOException;


public class MyCallbackHandler implements CallbackHandler {

 private static final Log log =
LogFactory.getLog(MyCallbackHandler.class);

 private String password;

 public void handle(Callback[] callbacks) throws IOException,
UnsupportedCallbackException {

     WSPasswordCallback pc = (WSPasswordCallback) callbacks[0];
     pc.setPassword(password);
 }

 public void setPassword(String password) {
     this.password = password;
 }
}

--- end example code MyCallbackHandler.java ---



--
Gary Weaver
Internet Framework Services
Office of Information Technology
Duke University




--
View this message in context: 
http://www.nabble.com/configuring-password-for-services-via-Spring-in-Apache-CXF-2.1.1-%28so-that-username%2C-password%2C-endpoint%2C-etc.-can-be-set-on-client-bean-via-Spring%29-tp18491639p18501459.html
Sent from the cxf-user mailing list archive at Nabble.com.


---
Daniel Kulp
[EMAIL PROTECTED]
http://www.dankulp.com/blog




Reply via email to