Hi, I want to comment my experience on setting up a web service using WSF/Spring to expose and axis2 web service and integrating this with Spring Security so the authentication gets done by spring.
I will asume you have already set up a web service with WSF/Spring (just WSF for brevity) + WS-Signature (using rampart) and that you know about spring security, I will only show how to add an axis2 handler to WSF to intercept incoming web services operations and authenticate them using spring security and WS-Signature.
Axis2 Handler for Spring Security Integration
import util.ServiceContext;
import org.apache.axis2.AxisFault;
import org.apache.axis2.context.MessageContext;
import org.apache.axis2.engine.Handler;
import org.apache.axis2.handlers.AbstractHandler;
import org.apache.ws.security.WSSecurityEngineResult;
import org.apache.ws.security.handler.WSHandlerConstants;
import org.apache.ws.security.handler.WSHandlerResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import javax.security.auth.Subject;
import java.security.cert.X509Certificate;
import java.util.Iterator;
import java.util.List;
/**
* Executed in a custom phase after the security phase has been proccesed
*
* Creado por: jaime
* 28/12/11
*/
public class SpringSecurityHandler extends AbstractHandler {
@Override
public InvocationResponse invoke(MessageContext msgContext) throws AxisFault {
// get xmldsig and authenticate
List<Object> results = (List<Object>) msgContext.getProperty(WSHandlerConstants.RECV_RESULTS);
if (results == null) {
return InvocationResponse.ABORT;
}
for (Iterator iter = results.iterator(); iter.hasNext(); ) {
WSHandlerResult hr = (WSHandlerResult) iter.next();
if (hr == null || hr.getResults() == null) {
return InvocationResponse.ABORT;
}
for (Iterator it = hr.getResults().iterator(); it.hasNext(); ) {
WSSecurityEngineResult er = (WSSecurityEngineResult) it.next();
if (er != null && er.get(WSSecurityEngineResult.TAG_X509_CERTIFICATE) instanceof X509Certificate) {
X509Certificate x509Cert= (X509Certificate) er.get(WSSecurityEngineResult.TAG_X509_CERTIFICATE);
// TODO check against database
SecurityContextHolder.getContext().setAuthentication(new UsernamePasswordAuthenticationToken(x509Cert, null));
return InvocationResponse.CONTINUE;
}
}
}
return InvocationResponse.ABORT;
}
}
axis2Config.xml (Displaying only modified parts)
<bean id="axis2InFaultPhaseOrder"> <property name="phaseOrderType" value="InFaultFlow"></property> <property name="phases"> <list> <ref bean="axis2AddressingPhase"/> <ref bean="security"/> <ref bean="springSecurityCheckPhase"/> <ref bean="preDispatchPhase"/> <bean id="InFaultDispatchPhase"> <property name="name" value="Dispatch"></property> <property name="clazz" value="org.apache.axis2.engine.DispatchPhase"></property> <property name="handlers"> <list> <ref bean="RequestURI"/> <ref bean="SOAPAction"/> <ref bean="RequestURIOperation"/> <ref bean="SOAPMessageBody"/> <ref bean="HTTPLocationBased"/> </list> </property> </bean> </list> </property> </bean> <bean id="axis2InPhaseOrder"> <property name="phaseOrderType" value="InFlow"></property> <property name="phases"> <list> <ref bean="axis2TransportPhase"/> <ref bean="axis2AddressingPhase"/> <ref bean="security"/> <ref bean="springSecurityCheckPhase"/> <ref bean="preDispatchPhase"/> <bean id="InDispatchPhase"> <property name="name" value="Dispatch"></property> <property name="clazz" value="org.apache.axis2.engine.DispatchPhase"></property> <property name="handlers"> <list> <ref bean="RequestURI"/> <ref bean="SOAPAction"/> <ref bean="RequestURIOperation"/> <ref bean="SOAPMessageBody"/> <ref bean="HTTPLocationBased"/> </list> </property> </bean> </list> </property> </bean> .... <!-- add a handler in the Security phase after SecurityInHandler--> <bean id="springSecurityHandlerBean"> <property name="name" value="SpringSecurityHandler"></property> <property name="clazz" value="com.kprtech.service.ws.security.SpringSecurityHandler"></property> </bean> <bean id="springSecurityCheckPhase"> <property name="name" value="SpringSecurityCheckPhase" /> <property name="handlers"> <list> <ref bean="springSecurityHandlerBean"/> </list> </property> </bean>
The last part of xml is creating a new phase with a handler (SpringSecurityHandler) and attaching it to axis2InPhaseOrder and axis2InFaultPhaseOrder after the Security proccesing of rampart.