Search code examples
cxfws-securitywildfly-12

WSS4JInInterceptor migrate to wildfly12


I'm planing to migrate jboss 5 to wildfly 12. There is a web service which is using org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor to validate access to the service. For that it uses configuration in jboss-cxf.xml as below.

<jaxws:inInterceptors>
     <bean class="org.apache.cxf.binding.soap.saaj.SAAJInInterceptor"/>
     <bean class="org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor">
           <property name="properties">
               <map>
                    <entry key="action"  value="UsernameToken"/>
                    <entry key="passwordType" value="PasswordText"/>
                    <entry key="passwordCallbackClass" value="com.xxx.xxx.ws.wsse.ServerPasswordCallback"/>
               </map>
             </property>
     </bean>
</jaxws:inInterceptors> 

In wildfly12 its not reading this xml. There is new configuration file called 'jboss-webservices.xml'. but i couldn't find out a way to migrate this to new version.
Please help on this


Solution

  • I solved this using a ininterceptor annotation. I added org.apache.cxf.interceptor.InInterceptors annotation & provided customized class to set values to required fields of WSS4JInInterceptor & added WSS4JInInterceptor to interceptor chain.

    @InInterceptors(interceptors = {"com.xxx.xx.ws.wsse.WSSecurityInterceptor"})
    @WebService
    @Stateless
    public class OrganizationImportServiceImpl{...enter code here
    

    Here is the com.xxx.xx.ws.wsse.WSSecurityInterceptor class

    package com.xxx.xx.ws.wsse;
    
    import java.util.HashMap;
    import java.util.Map;
    import org.apache.cxf.interceptor.Fault;
    import org.apache.cxf.interceptor.Interceptor;
    import org.apache.cxf.message.Message;
    import org.apache.cxf.phase.AbstractPhaseInterceptor;
    import org.apache.cxf.phase.Phase;
    import org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor;
    
    public class WSSecurityInterceptor extends AbstractPhaseInterceptor<Message>{
    
    public WSSecurityInterceptor() {
        super(Phase.PRE_PROTOCOL);
    }   
    public WSSecurityInterceptor(String phase) {
        super(Phase.PRE_PROTOCOL);
    }
    
    @Override
    public void handleMessage(Message message) throws Fault {
    
        Map<String, Object> props = new HashMap<String, Object>();
        props.put("action", "UsernameToken");
        props.put("passwordCallbackClass", "com.xxx.xx.ws.wsse.ServerPasswordCallback");
        props.put("passwordType", "PasswordText");
    
        WSS4JInInterceptor wss4jInHandler = new WSS4JInInterceptor(props);
    
        message.getInterceptorChain().add((Interceptor<? extends Message>) wss4jInHandler);
     }
    }
    

    Then set valid password within callback handler class. here is the callback handler class.

    package com.xxx.xx.ws.wsse;
    
    import java.io.IOException;
    import java.util.HashMap;
    import java.util.Map;
    
    import javax.security.auth.callback.Callback;
    import javax.security.auth.callback.CallbackHandler;
    import javax.security.auth.callback.UnsupportedCallbackException;
    import org.apache.wss4j.common.ext.WSPasswordCallback;
    
    public class ServerPasswordCallback implements CallbackHandler {
    
       private Map<String, String> passwords = new HashMap<String, String>();
    
       public ServerPasswordCallback() {
         super();
         passwords.put("testuser", "testpwd");
       }
    
       public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
    
        WSPasswordCallback pc = (WSPasswordCallback) callbacks[0];
    
        if (pc.getIdentifier() == null) {
            throw new IOException("authentication failure. required username password to proceed ..");
        }
    
        if (passwords.containsKey(pc.getIdentifier())) {
           // set the password on the callback. This will be compared to the
           // password which was sent from the client.
            pc.setPassword(passwords.get(pc.getIdentifier()));
        } else {
            throw new IOException("authentication failure. invalid user name or password ");
        }
      } 
    }
    

    Then password validation perform in cxf-rt-ws-security module.