Document Migration to SecurityContextHolderFilter

Closes gh-12098
This commit is contained in:
Rob Winch 2022-10-27 15:12:45 -05:00
parent 1dd13e69a4
commit aac1261f0c
3 changed files with 93 additions and 23 deletions

View File

@ -13,6 +13,21 @@ endif::[]
== Servlet == Servlet
=== Explicit Save SecurityContextRepository
In Spring Security 5, the default behavior is for the xref:servlet/authentication/architecture.adoc#servlet-authentication-securitycontext[`SecurityContext`] to automatically be saved to the xref:servlet/authentication/persistence.adoc#securitycontextrepository[`SecurityContextRepository`] using the xref:servlet/authentication/persistence.adoc#securitycontextpersistencefilter[`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 xref:servlet/authentication/persistence.adoc#securitycontextholderfilter[`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.
To opt into the new Spring Security 6 default, the following configuration can be used.
include::partial$servlet/architecture/security-context-explicit.adoc[]
[[requestcache-query-optimization]] [[requestcache-query-optimization]]
=== Optimize Querying of `RequestCache` === Optimize Querying of `RequestCache`

View File

@ -144,29 +144,8 @@ image::{figures}/securitycontextholderfilter.png[]
<1> Before running the rest of the application, `SecurityContextHolderFilter` loads the `SecurityContext` from the `SecurityContextRepository` and sets it on the `SecurityContextHolder`. <1> Before running the rest of the application, `SecurityContextHolderFilter` loads the `SecurityContext` from the `SecurityContextRepository` and sets it on the `SecurityContextHolder`.
<2> Next, the application is ran. <2> Next, the application is ran.
Unlike, xref:servlet/authentication/persistence.adoc#securitycontextpersistencefilter[`SecurityContextPersisteneFilter`], `SecurityContextHolderFilter` only loads the `SecurityContext` it does not save the `SecurityContext`. Unlike, xref:servlet/authentication/persistence.adoc#securitycontextpersistencefilter[`SecurityContextPersistenceFilter`], `SecurityContextHolderFilter` only loads the `SecurityContext` it does not save the `SecurityContext`.
This means that when using `SecurityContextHolderFilter`, it is required that the `SecurityContext` is explicitly saved. This means that when using `SecurityContextHolderFilter`, it is required that the `SecurityContext` is explicitly saved.
.Explicit Saving of SecurityContext
====
.Java
[source,java,role="primary"]
----
public SecurityFilterChain filterChain(HttpSecurity http) {
http
// ...
.securityContext((securityContext) -> securityContext
.requireExplicitSave(true)
);
return http.build();
}
----
.XML include::partial$servlet/architecture/security-context-explicit.adoc[]
[source,xml,role="secondary"]
----
<http security-context-explicit-save="true">
<!-- ... -->
</http>
----
====

View File

@ -0,0 +1,76 @@
.Explicit Saving of SecurityContext
====
.Java
[source,java,role="primary"]
----
public SecurityFilterChain filterChain(HttpSecurity http) {
http
// ...
.securityContext((securityContext) -> securityContext
.requireExplicitSave(true)
);
return http.build();
}
----
.Kotlin
[source,kotlin,role="secondary"]
----
@Bean
open fun springSecurity(http: HttpSecurity): SecurityFilterChain {
http {
securityContext {
requireExplicitSave = true
}
}
return http.build()
}
----
.XML
[source,xml,role="secondary"]
----
<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
[source,java,role="primary"]
----
SecurityContextHolder.setContext(securityContext);
----
.Kotlin
[source,kotlin,role="secondary"]
----
SecurityContextHolder.setContext(securityContext)
----
====
should be replaced with
.Setting `SecurityContextHolder` with `SecurityContextHolderFilter`
====
.Java
[source,java,role="primary"]
----
SecurityContextHolder.setContext(securityContext);
securityContextRepository.saveContext(securityContext, httpServletRequest, httpServletResponse);
----
.Kotlin
[source,kotlin,role="secondary"]
----
SecurityContextHolder.setContext(securityContext)
securityContextRepository.saveContext(securityContext, httpServletRequest, httpServletResponse)
----
====