For the latest stable version, please use Spring Security 6.2.4!

Session Management Migrations

The following steps relate to how to finish migrating session management support.

Require Explicit Saving of SecurityContextRepository

In Spring Security 5, the default behavior is for the SecurityContext to automatically be saved to the SecurityContextRepository using the SecurityContextPersistenceFilter. Saving must be done just prior to the HttpServletResponse being committed and just before SecurityContextPersistenceFilter. Unfortunately, automatic persistence of the SecurityContext can surprise users when it is done prior to the request completing (i.e. just prior to committing the HttpServletResponse). It also is complex to keep track of the state to determine if a save is necessary causing unnecessary writes to the SecurityContextRepository (i.e. HttpSession) at times.

In Spring Security 6, the default behavior is that the SecurityContextHolderFilter will only read the SecurityContext from SecurityContextRepository and populate it in the SecurityContextHolder. Users now must explicitly save the SecurityContext with the SecurityContextRepository if they want the SecurityContext to persist between requests. This removes ambiguity and improves performance by only requiring writing to the SecurityContextRepository (i.e. HttpSession) when it is necessary.

Saving the context is also needed when clearing it out, for example during logout. Refer to this section to know more about that.

If you are explicitly opting into Spring Security 6’s new defaults, the following configuration can be removed to accept the Spring Security 6 defaults.

Explicit Saving of SecurityContext
  • Java

  • Kotlin

  • XML

public SecurityFilterChain filterChain(HttpSecurity http) {
	http
		// ...
		.securityContext((securityContext) -> securityContext
			.requireExplicitSave(true)
		);
	return http.build();
}
@Bean
open fun springSecurity(http: HttpSecurity): SecurityFilterChain {
    http {
        securityContext {
            requireExplicitSave = true
        }
    }
    return http.build()
}
<http security-context-explicit-save="true">
	<!-- ... -->
</http>

Upon using the configuration, it is important that any code that sets the SecurityContextHolder with a SecurityContext also saves the SecurityContext to the SecurityContextRepository if it should be persisted between requests.

For example, the following code:

Setting SecurityContextHolder with SecurityContextPersistenceFilter
  • Java

  • Kotlin

SecurityContextHolder.setContext(securityContext);
SecurityContextHolder.setContext(securityContext)

should be replaced with

Setting SecurityContextHolder with SecurityContextHolderFilter
  • Java

  • Kotlin

SecurityContextHolder.setContext(securityContext);
securityContextRepository.saveContext(securityContext, httpServletRequest, httpServletResponse);
SecurityContextHolder.setContext(securityContext)
securityContextRepository.saveContext(securityContext, httpServletRequest, httpServletResponse)

Multiple SecurityContextRepository

In Spring Security 5, the default SecurityContextRepository was HttpSessionSecurityContextRepository.

In Spring Security 6, the default SecurityContextRepository is DelegatingSecurityContextRepository. If you configured the SecurityContextRepository only for the purpose of updating to 6.0, you can remove it completely.

Deprecation in SecurityContextRepository

There are no further migration steps for this deprecation.

Optimize Querying of RequestCache

In Spring Security 5, the default behavior is to query the saved request on every request. This means that in a typical setup, that in order to use the RequestCache the HttpSession is queried on every request.

In Spring Security 6, the default is that RequestCache will only be queried for a cached request if the HTTP parameter continue is defined. This allows Spring Security to avoid unnecessarily reading the HttpSession with the RequestCache.

In Spring Security 5 the default is to use HttpSessionRequestCache which will be queried for a cached request on every request. If you are not overriding the defaults (i.e. using NullRequestCache), then the following configuration can be used to explicitly opt into the Spring Security 6 behavior in Spring Security 5.8:

RequestCache Only Checks for Saved Requests if continue Parameter Present
  • Java

  • Kotlin

  • XML

@Bean
DefaultSecurityFilterChain springSecurity(HttpSecurity http) throws Exception {
	HttpSessionRequestCache requestCache = new HttpSessionRequestCache();
	requestCache.setMatchingRequestParameterName("continue");
	http
		// ...
		.requestCache((cache) -> cache
			.requestCache(requestCache)
		);
	return http.build();
}
@Bean
open fun springSecurity(http: HttpSecurity): SecurityFilterChain {
    val httpRequestCache = HttpSessionRequestCache()
    httpRequestCache.setMatchingRequestParameterName("continue")
    http {
        requestCache {
            requestCache = httpRequestCache
        }
    }
    return http.build()
}
<http auto-config="true">
	<!-- ... -->
	<request-cache ref="requestCache"/>
</http>

<b:bean id="requestCache" class="org.springframework.security.web.savedrequest.HttpSessionRequestCache"
	p:matchingRequestParameterName="continue"/>