WSF/Spring, Axis2 + Spring Security with WS-Signature

29/12/2011 a las 5:15 pm | Escrito en Informatica, Java | Deja un comentario

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.

Beware of using your own ThreadPoolTaskExecutor and @Autowired dependencies

16/12/2011 a las 7:32 pm | Escrito en Informatica, Java | Deja un comentario
Etiquetas: ,

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

 

Página siguiente »

Blog de WordPress.com. | Theme: Pool by Borja Fernandez.
Entradas y comentarios: feeds.

Seguir

Get every new post delivered to your Inbox.