From d860775b45f17bd607d21f82686bcd82741016a3 Mon Sep 17 00:00:00 2001 From: Rob Winch Date: Fri, 28 Oct 2022 15:41:25 -0500 Subject: [PATCH] Document Defer load CsrfToken Closes gh-12105 --- .../DeferHttpSessionJavaConfigTests.java | 5 -- .../http/DeferHttpSessionTests-Explicit.xml | 7 +- docs/modules/ROOT/pages/migration.adoc | 84 ++++++++++++++++--- 3 files changed, 72 insertions(+), 24 deletions(-) diff --git a/config/src/test/java/org/springframework/security/config/annotation/web/configuration/DeferHttpSessionJavaConfigTests.java b/config/src/test/java/org/springframework/security/config/annotation/web/configuration/DeferHttpSessionJavaConfigTests.java index fe5cca2527..28b2adaf9a 100644 --- a/config/src/test/java/org/springframework/security/config/annotation/web/configuration/DeferHttpSessionJavaConfigTests.java +++ b/config/src/test/java/org/springframework/security/config/annotation/web/configuration/DeferHttpSessionJavaConfigTests.java @@ -34,8 +34,6 @@ import org.springframework.security.config.test.SpringTestContextExtension; import org.springframework.security.web.DefaultSecurityFilterChain; import org.springframework.security.web.FilterChainProxy; import org.springframework.security.web.csrf.CsrfTokenRequestAttributeHandler; -import org.springframework.security.web.csrf.HttpSessionCsrfTokenRepository; -import org.springframework.security.web.csrf.LazyCsrfTokenRepository; import org.springframework.security.web.savedrequest.HttpSessionRequestCache; import static org.mockito.ArgumentMatchers.anyBoolean; @@ -81,8 +79,6 @@ public class DeferHttpSessionJavaConfigTests { @Bean DefaultSecurityFilterChain springSecurity(HttpSecurity http) throws Exception { - LazyCsrfTokenRepository csrfRepository = new LazyCsrfTokenRepository(new HttpSessionCsrfTokenRepository()); - csrfRepository.setDeferLoadToken(true); HttpSessionRequestCache requestCache = new HttpSessionRequestCache(); requestCache.setMatchingRequestParameterName("continue"); CsrfTokenRequestAttributeHandler requestHandler = new CsrfTokenRequestAttributeHandler(); @@ -103,7 +99,6 @@ public class DeferHttpSessionJavaConfigTests { ) .csrf((csrf) -> csrf .csrfTokenRequestHandler(requestHandler) - .csrfTokenRepository(csrfRepository) ); // @formatter:on return http.build(); diff --git a/config/src/test/resources/org/springframework/security/config/http/DeferHttpSessionTests-Explicit.xml b/config/src/test/resources/org/springframework/security/config/http/DeferHttpSessionTests-Explicit.xml index cbfdfa90a3..27af272bcf 100644 --- a/config/src/test/resources/org/springframework/security/config/http/DeferHttpSessionTests-Explicit.xml +++ b/config/src/test/resources/org/springframework/security/config/http/DeferHttpSessionTests-Explicit.xml @@ -30,18 +30,13 @@ security-context-explicit-save="true" use-authorization-manager="true"> - + - - diff --git a/docs/modules/ROOT/pages/migration.adoc b/docs/modules/ROOT/pages/migration.adoc index 0dbb919b11..8c81515009 100644 --- a/docs/modules/ROOT/pages/migration.adoc +++ b/docs/modules/ROOT/pages/migration.adoc @@ -13,6 +13,64 @@ endif::[] == Servlet +=== Defer Loading CsrfToken + +In Spring Security 5, the default behavior is that the `CsrfToken` will be loaded on every request. +This means that in a typical setup, the `HttpSession` must be read for every request even if it is unnecessary. + +In Spring Security 6, the default is that the lookup of the `CsrfToken` will be deferred until it is needed. + +To opt into the new Spring Security 6 default, the following configuration can be used. + +.Defer Loading `CsrfToken` +==== +.Java +[source,java,role="primary"] +---- +@Bean +DefaultSecurityFilterChain springSecurity(HttpSecurity http) throws Exception { + CsrfTokenRequestAttributeHandler requestHandler = new CsrfTokenRequestAttributeHandler(); + // set the name of the attribute the CsrfToken will be populated on + requestHandler.setCsrfRequestAttributeName("_csrf"); + http + // ... + .csrf((csrf) -> csrf + .csrfTokenRequestHandler(requestHandler) + ); + return http.build(); +} +---- + +.Kotlin +[source,kotlin,role="secondary"] +---- +@Bean +open fun springSecurity(http: HttpSecurity): SecurityFilterChain { + val requestHandler = CsrfTokenRequestAttributeHandler() + // set the name of the attribute the CsrfToken will be populated on + requestHandler.setCsrfRequestAttributeName("_csrf") + http { + csrf { + csrfTokenRequestHandler = requestHandler + } + } + return http.build() +} +---- + +.XML +[source,xml,role="secondary"] +---- + + + + + +---- +==== + === 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`]. @@ -170,10 +228,10 @@ static PermissionEvaluator permissionEvaluator() { [source,kotlin,role="secondary"] ---- companion object { - @Bean - fun permissionEvaluator(): PermissionEvaluator { - // ... your evaluator - } + @Bean + fun permissionEvaluator(): PermissionEvaluator { + // ... your evaluator + } } ---- ==== @@ -186,9 +244,9 @@ to: ---- @Bean static MethodSecurityExpressionHandler expressionHandler() { - var expressionHandler = new DefaultMethodSecurityExpressionHandler(); - expressionHandler.setPermissionEvaluator(myPermissionEvaluator); - return expressionHandler; + var expressionHandler = new DefaultMethodSecurityExpressionHandler(); + expressionHandler.setPermissionEvaluator(myPermissionEvaluator); + return expressionHandler; } ---- @@ -196,12 +254,12 @@ static MethodSecurityExpressionHandler expressionHandler() { [source,kotlin,role="secondary"] ---- companion object { - @Bean - fun expressionHandler(): MethodSecurityExpressionHandler { - val expressionHandler = DefaultMethodSecurityExpressionHandler - expressionHandler.setPermissionEvaluator(myPermissionEvaluator) - return expressionHandler - } + @Bean + fun expressionHandler(): MethodSecurityExpressionHandler { + val expressionHandler = DefaultMethodSecurityExpressionHandler + expressionHandler.setPermissionEvaluator(myPermissionEvaluator) + return expressionHandler + } } ---- ====