Thursday 18 September 2014

Apache CXF+Spring: How to add authentication (dynamic credentials: from db, AD, etc)

 Server exposing Web Service


@WebService
public interface MyWebService {

...

}

@WebService(endpointInterface = "com.micharg.MyWebService")
public class MyWebServiceImpl implements MyWebService {

...
}


public interface WebServiceAuthenticationService {

}



@Service("webServiceAuthenticationService")
public class WebServiceAuthenticationServiceImpl implements Validator, WebServiceAuthenticationService {

    @Autowired
    private AuthenticationService authenticationService;
  
   
    @Override
    public Credential validate(Credential credential, RequestData data) throws WSSecurityException {

         String candidateUsername = credential.getUsernametoken().getName();
         String candidatePassword = credential.getUsernametoken().getPassword();
       
        boolean isUserAuthenticated = authenticationService.authenticate(candidateUsername, candidatePassword);
  
        if(!isUserAuthenticated ) {
             throw new WSSecurityException("Wrong credentials (" + candidateUsername + ", " + candidatePassword + "); can not execute web service");
         }
         
        return credential;
    }

}

<bean id="inbound-security" class="org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor">
        <constructor-arg>
            <map>
                <entry key="action" value="UsernameToken" />
                <entry key="passwordType" value="PasswordText" />
            </map>
        </constructor-arg>
 </bean>
   
<!-- Add authentication to the web service that listens to endpoint http://mydomain/myendpoint; -->
<jaxws:endpoint id="myWebService" implementor="#myWebServiceImpl" address="/myendpoint">
   
        <jaxws:properties>
            <entry key="ws-security.ut.validator" value-ref="webServiceAuthenticationService" />
        </jaxws:properties>
       
        <jaxws:inInterceptors>
            <ref bean="inbound-security" />
        </jaxws:inInterceptors>
</jaxws:endpoint>




Client consuming Web Service


<!-- consume web service located on http://foo.com/myendpoint

<jaxws:client id="myWebServicesClient"
            serviceClass="com.micharg.MyWebService"
            address="http://foo.com/myendpoint">
           
            <jaxws:outInterceptors>
                <ref bean="outbound-security" />
            </jaxws:outInterceptors>
    </jaxws:client>





<bean class="eu.europa.europarl.apapeople.people.web.ws.WebServicesCallbackHandler" id="webServicesCallbackHandler" />


<bean class="org.apache.cxf.ws.security.wss4j.WSS4JOutInterceptor" id="outbound-security">
        <constructor-arg>
            <map>
                <entry key="action" value="UsernameToken"/> 
                <entry key="user" value="dummy password - passwordCallbackClass overrides it"/> 
                <entry key="passwordType" value="PasswordText"/>
                <entry key="passwordCallbackRef" value-ref="webServicesCallbackHandler"/>          
            </map>
        </constructor-arg>
    </bean>   




public class WebServicesCallbackHandler implements CallbackHandler {

    private String username = "...";
    private String password = "...";
   
    @Override
    public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
        WSPasswordCallback c = (WSPasswordCallback) callbacks[0];
        c.setIdentifier(username);
        c.setPassword(password);
    }

}
   

No comments:

Post a Comment