Configuring Spring Security to persist the SecurityContext to places other than session between requests
October 21, 2011
Yeah I agree, I suck at titles :) But, again and again, Spring guys are cool ass kickers :)
By default, Spring Security keeps the SecurityContext in session objects of user between requests. SecurityContextPersistenceFilter manages this task. When a request comes, it reads the SecurityContext from a security context repository (which I will mention now), puts it to SecurityContextHolder to be used by other filters and the application. And when request is completed, it clears the SecurityContextHolder and puts the SecurityContext to the repository. The repository I mentioned here is the HttpSessionSecurityContextRepository class which is an implementation of SecurityContextRepository interface. This interface is responsible for persisting SecurityContext objects between requests and used by SecurityContextPersistenceFilter.
For a requirement we get, we need to read the logged in user information from memcached, not the http session. With a little investigation, we saw the SecurityContextRepository interface and its default HttpSessionSecurityContextRepository implementation. We figured out that with a custom implementation of that interface, Spring Security will still work quite well for our situation. So we coded our implementation and tried to inject it into the SpringSecurityContextPersistenceFilter.
Configuring Spring Security to use the custom repository was a more challenging task than writing a custom implementation for us because we could not see a point for the configuration :) In the reference documentation, the bean definition below is given:
<bean id="securityContextPersistenceFilter" class="org.springframework.security.web.context.SecurityContextPersistenceFilter"> <property name='securityContextRepository'> <bean class='org.springframework.security.web.context.HttpSessionSecurityContextRepository'> <property name='allowSessionCreation' value='false' /> </bean> </property> </bean>
And this explanation is given:
Alternatively you could provide a null implementation of the SecurityContextRepository interface, which will prevent the security context from being stored, even if a session has already been created during the request. (Section 8.3)
So we copied the bean definition above and replaced the default repository with ours.
When we started the application, we traced the logs and saw that Spring Security was still using the default http session repository instead of our repository.
After a little bit more investigation, we understood that we had to use the “security-context-repository-ref” attribute of “http” namespace in configuration. Although a SecurityPersistenceContextFilter bean definition is provided, when “http” namespace is used, Spring Security creates its own SecurityPersistenceContextFilter with defaults. So to customize it, “security-context-repository” attribute must be used.
So here is the appropriate configuration:
<sec:http auto-config="false" security-context-repository-ref="memcachedSecurityContextRepository"> <!-- ... --> </sec:http> <bean id="memcachedSecurityContextRepository" class="...MemcachedSecurityContextRepository" />
We could not understand why Section 8.3 of the Spring Security reference does not state this.
I also wrote a similar post on a related question on the stackoverflow which you can have a look with this link: http://stackoverflow.com/questions/2504590/how-can-i-use-spring-security-without-sessions/7653699#7653699
Also javadocs are quite useful: http://static.springsource.org/spring-security/site/docs/3.0.x/apidocs/org/springframework/security/web/context/SecurityContextPersistenceFilter.html http://static.springsource.org/spring-security/site/docs/3.0.x/apidocs/org/springframework/security/web/context/SecurityContextRepository.html