Category: Security

Inherit Spring Security Context in Child Threads

2010-04-04

By default, Spring Security context is bound to ThreadLocal, which may catch you by surprise in some cases involving spawned threads.

So I setup my security infrastructure to authenticate users, populate their details from database, grant them authorities, I configure AccessDecisionManager and put @Secured annotations on my business methods to assert those authorities, etc. It all works well until my business code evolves to include asynchronous invocations. Then I find myself wondering: why am I getting AuthenticationCredentialsNotFoundException in places where the user is obviously authenticated?

Turns out that when a new thread is started it knows nothing about the security context of its parent thread. So if AccessDecisionManager gets called (e.g. if a @Secured method is invoked) from within the child thread, you get a security exception.

To work around that, you should change the SecurityContextHolder strategy to use InheritableThreadLocal for storing the security context. You can do that in code:

SecurityContextHolder.setStrategyName(SecurityContextHolder.MODE_INHERITABLETHREADLOCAL)

… or in XML configuration (which is better since you’ll only need to call the static method once during application startup):

<bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
    <property name="targetClass"
        value="org.springframework.security.context.SecurityContextHolder"/>
    <property name="targetMethod" value="setStrategyName"/>
    <property name="arguments"><list><value>MODE_INHERITABLETHREADLOCAL</value></list></property>
</bean>

Note however, that you cannot share security context among sibling threads (e.g. in a thread pool). This method only works for child threads that are spawned by a thread that already contains a populated SecurityContext.