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.

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.

Reply via email to