Ensar Basri Kahveci

overly distributed

Configuring Spring Security to persist the SecurityContext to places other than session between requests

Posted at — Oct 21, 2011

java - spring - spring security 

Yeah I agree, I suck at titles :) But, again and again, Spring guys are real badasses :)

By default, Spring Security keeps the SecurityContext object in session objects of user between requests. SecurityContextPersistenceFilter manages this task. When a request comes, it reads the SecurityContext object from a security context repository (which I will mention in a second), 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 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

comments powered by Disqus