WSF/Spring, Axis2 + Spring Security with WS-Signature
29/12/2011 a las 5:15 pm | Escrito en Informatica, Java | Deja un comentarioHi, 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.
Beware of using your own ThreadPoolTaskExecutor and @Autowired dependencies
16/12/2011 a las 7:32 pm | Escrito en Informatica, Java | Deja un comentarioEtiquetas: autowired, InitializingBean
I just want to share my experience after debugging a bug caused because my own implementation of ThreadPoolTaskExecutor was using @Autowired dependencies and so initializing to early the autowired beans, which caused that @Transactional, @PreAuthorize annotations wasn’t applying its proxies.
I had something like this:
public class MyThreadPoolTaskExecutor extends ThreadPoolTaskExecutor {
@Autowired
SecurityService securityService; // this initializes SecurityService bean too early
@Override
public <T> Future<T> submit(final Callable<T> task) {
securityService.doSomething();
...
...
}
}
But it should be something like:
public class MyThreadPoolTaskExecutor extends ThreadPoolTaskExecutor {
@Override
public <T> Future<T> submit(final Callable<T> task) {
// get access through a statically exposed spring context.
ServiceContext.getBean("securityService").doSomething();
...
...
}
}
public class ServiceContext implements ApplicationContextAware {
private static ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
/**
* Get the bean from the Spring application context.
*
* @param beanName
* @return
*/
public static Object getBean(String beanName) {
if (applicationContext == null) {
throw new IllegalStateException(
"No Spring web application context found");
}
if (!applicationContext.containsBean(beanName)) {
{
throw new IllegalArgumentException("Spring bean not found: "
+ beanName);
}
}
return applicationContext.getBean(beanName);
}
}
It seems to be related to the fact that autowired dependencies (other beans) of beans of type org.springframework.beans.factory.InitializingBean don’t get proxied correctly
Blog de WordPress.com. | Theme: Pool by Borja Fernandez.
Entradas y comentarios: feeds.