mirror of
https://github.com/spring-projects/spring-security.git
synced 2025-03-03 20:09:18 +00:00
Document Migration to SecurityContextHolderFilter
Closes gh-12098
This commit is contained in:
parent
1dd13e69a4
commit
aac1261f0c
@ -13,6 +13,21 @@ endif::[]
|
||||
|
||||
== 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]]
|
||||
=== Optimize Querying of `RequestCache`
|
||||
|
||||
|
@ -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`.
|
||||
<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.
|
||||
|
||||
.Explicit Saving of SecurityContext
|
||||
====
|
||||
.Java
|
||||
[source,java,role="primary"]
|
||||
----
|
||||
public SecurityFilterChain filterChain(HttpSecurity http) {
|
||||
http
|
||||
// ...
|
||||
.securityContext((securityContext) -> securityContext
|
||||
.requireExplicitSave(true)
|
||||
);
|
||||
return http.build();
|
||||
}
|
||||
----
|
||||
|
||||
.XML
|
||||
[source,xml,role="secondary"]
|
||||
----
|
||||
<http security-context-explicit-save="true">
|
||||
<!-- ... -->
|
||||
</http>
|
||||
----
|
||||
====
|
||||
include::partial$servlet/architecture/security-context-explicit.adoc[]
|
@ -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)
|
||||
----
|
||||
====
|
Loading…
x
Reference in New Issue
Block a user