Thread safe in Spring security

We have a project using spring security for using auth. At the last filter chain is a custom filter which applies a id to the spring security managed User object which is used as principal in security context.

When the same user from the same session send multiple requests which tomcat would spawn multiple threads to handle, after the user in thread1 obtains the id and going to do something with the ID, i got ID nullpointer exception.

It drives me nuts to find out why since the Spring security context is Thread local which should not be affected by multi-threading.

It turns out :

In an application which receives concurrent requests in a single session, the same SecurityContext instance will be shared between threads. Even though a ThreadLocal is being used, it is the same instance that is retrieved from the HttpSession for each thread. This has implications if you wish to temporarily change the context under which a thread is running. If you just useSecurityContextHolder.getContext().setAuthentication(anAuthentication), then the Authentication object will change in all concurrent threads which share the same SecurityContext instance. You can customize the behaviour of SecurityContextPersistenceFilter to create a completely new SecurityContext for each request, preventing changes in one thread from affecting another. Alternatively you can create a new instance just at the point where you temporarily change the context. The method SecurityContextHolder.createEmptyContext() always returns a new context instance.

From here 5.4.4 : http://docs.spring.io/spring-security/site/docs/3.0.x/reference/technical-overview.html

Another answer from Luke Taylor who is the author of many Spring Security class:

http://forum.spring.io/forum/spring-projects/security/102508-securitycontext-and-thread-safe

In a Web application you will use the ThreadLocalSecurityContextHolderStrategy which interacts with SecurityContextPersistenceFilter.

The Java Doc of SecurityContextPersistenceFilter starts with:

Populates the {@link SecurityContextHolder} with information obtained from the configured {@link SecurityContextRepository} prior to the request and stores it back in the repository once the request has completed and clearing the context holder. By default it uses an {@link HttpSessionSecurityContextRepository}. See this class for information HttpSession related configuration options.

Btw: HttpSessionSecurityContextRepository is the only implementation of SecurityContextRepository (I have found in the default libs)

It works like this:

  • The HttpSessionSecurityContextRepository uses the httpSession (Key=”SPRING_SECURITY_CONTEXT”) to store an SecurityContext Object.
  • The SecurityContextPersistenceFilter is an filter that uses an SecurityContextRepository for example the HttpSessionSecurityContextRepository to load and store SecurityContext Objects. If an HttpRequest passes the filter, the filter get the SecurityContext from the repository and put it in the SecurityContextHolder (SecurityContextHolder#setContext)
  • The SecurityContextHolder has two methods setContext and getContext. Both uses a SecurityContextHolderStrategy to specify what exactly is done in the set- and get-Context methods. – For example the ThreadLocalSecurityContextHolderStrategy uses a thread local to store the context.

So in summary: The user principal (element of SecurityContext) is stored in the HTTP Session. And for each request it is put in a thread local from where you access it.

Here is a spring jira issue related to this:  https://jira.spring.io/browse/SEC-356

Now i need to implement my own SecurityContextRepository

This is a blog doing similar stuff

http://www.basrikahveci.com/configuring-spring-security-to-persist-the-securitycontext-to-places-other-then-session-between-requests/

spring security architecture

finally the whole picture in brief for spring security: two good articles

Part One &&and&& Part Two

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s