Skip to content

Commit d860775

Browse files
committed
Document Defer load CsrfToken
Closes gh-12105
1 parent 4938c39 commit d860775

File tree

3 files changed

+72
-24
lines changed

3 files changed

+72
-24
lines changed

config/src/test/java/org/springframework/security/config/annotation/web/configuration/DeferHttpSessionJavaConfigTests.java

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,6 @@
3434
import org.springframework.security.web.DefaultSecurityFilterChain;
3535
import org.springframework.security.web.FilterChainProxy;
3636
import org.springframework.security.web.csrf.CsrfTokenRequestAttributeHandler;
37-
import org.springframework.security.web.csrf.HttpSessionCsrfTokenRepository;
38-
import org.springframework.security.web.csrf.LazyCsrfTokenRepository;
3937
import org.springframework.security.web.savedrequest.HttpSessionRequestCache;
4038

4139
import static org.mockito.ArgumentMatchers.anyBoolean;
@@ -81,8 +79,6 @@ Service service() {
8179

8280
@Bean
8381
DefaultSecurityFilterChain springSecurity(HttpSecurity http) throws Exception {
84-
LazyCsrfTokenRepository csrfRepository = new LazyCsrfTokenRepository(new HttpSessionCsrfTokenRepository());
85-
csrfRepository.setDeferLoadToken(true);
8682
HttpSessionRequestCache requestCache = new HttpSessionRequestCache();
8783
requestCache.setMatchingRequestParameterName("continue");
8884
CsrfTokenRequestAttributeHandler requestHandler = new CsrfTokenRequestAttributeHandler();
@@ -103,7 +99,6 @@ DefaultSecurityFilterChain springSecurity(HttpSecurity http) throws Exception {
10399
)
104100
.csrf((csrf) -> csrf
105101
.csrfTokenRequestHandler(requestHandler)
106-
.csrfTokenRepository(csrfRepository)
107102
);
108103
// @formatter:on
109104
return http.build();

config/src/test/resources/org/springframework/security/config/http/DeferHttpSessionTests-Explicit.xml

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -30,18 +30,13 @@
3030
security-context-explicit-save="true"
3131
use-authorization-manager="true">
3232
<intercept-url pattern="/**" access="permitAll"/>
33-
<csrf request-handler-ref="requestHandler"
34-
token-repository-ref="csrfRepository"/>
33+
<csrf request-handler-ref="requestHandler"/>
3534
<request-cache ref="requestCache"/>
3635
<session-management authentication-strategy-explicit-invocation="true"/>
3736
</http>
3837

3938
<b:bean id="requestCache" class="org.springframework.security.web.savedrequest.HttpSessionRequestCache"
4039
p:matchingRequestParameterName="continue"/>
41-
<b:bean id="httpSessionCsrfRepository" class="org.springframework.security.web.csrf.HttpSessionCsrfTokenRepository"/>
42-
<b:bean id="csrfRepository" class="org.springframework.security.web.csrf.LazyCsrfTokenRepository"
43-
c:delegate-ref="httpSessionCsrfRepository"
44-
p:deferLoadToken="true"/>
4540
<b:bean id="requestHandler" class="org.springframework.security.web.csrf.CsrfTokenRequestAttributeHandler"
4641
p:csrfRequestAttributeName="_csrf"/>
4742
<b:import resource="CsrfConfigTests-shared-userservice.xml"/>

docs/modules/ROOT/pages/migration.adoc

Lines changed: 71 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,64 @@ endif::[]
1313

1414
== Servlet
1515

16+
=== Defer Loading CsrfToken
17+
18+
In Spring Security 5, the default behavior is that the `CsrfToken` will be loaded on every request.
19+
This means that in a typical setup, the `HttpSession` must be read for every request even if it is unnecessary.
20+
21+
In Spring Security 6, the default is that the lookup of the `CsrfToken` will be deferred until it is needed.
22+
23+
To opt into the new Spring Security 6 default, the following configuration can be used.
24+
25+
.Defer Loading `CsrfToken`
26+
====
27+
.Java
28+
[source,java,role="primary"]
29+
----
30+
@Bean
31+
DefaultSecurityFilterChain springSecurity(HttpSecurity http) throws Exception {
32+
CsrfTokenRequestAttributeHandler requestHandler = new CsrfTokenRequestAttributeHandler();
33+
// set the name of the attribute the CsrfToken will be populated on
34+
requestHandler.setCsrfRequestAttributeName("_csrf");
35+
http
36+
// ...
37+
.csrf((csrf) -> csrf
38+
.csrfTokenRequestHandler(requestHandler)
39+
);
40+
return http.build();
41+
}
42+
----
43+
44+
.Kotlin
45+
[source,kotlin,role="secondary"]
46+
----
47+
@Bean
48+
open fun springSecurity(http: HttpSecurity): SecurityFilterChain {
49+
val requestHandler = CsrfTokenRequestAttributeHandler()
50+
// set the name of the attribute the CsrfToken will be populated on
51+
requestHandler.setCsrfRequestAttributeName("_csrf")
52+
http {
53+
csrf {
54+
csrfTokenRequestHandler = requestHandler
55+
}
56+
}
57+
return http.build()
58+
}
59+
----
60+
61+
.XML
62+
[source,xml,role="secondary"]
63+
----
64+
<http>
65+
<!-- ... -->
66+
<csrf request-handler-ref="requestHandler"/>
67+
</http>
68+
<b:bean id="requestHandler"
69+
class="org.springframework.security.web.csrf.CsrfTokenRequestAttributeHandler"
70+
p:csrfRequestAttributeName="_csrf"/>
71+
----
72+
====
73+
1674
=== Explicit Save SecurityContextRepository
1775

1876
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() {
170228
[source,kotlin,role="secondary"]
171229
----
172230
companion object {
173-
@Bean
174-
fun permissionEvaluator(): PermissionEvaluator {
175-
// ... your evaluator
176-
}
231+
@Bean
232+
fun permissionEvaluator(): PermissionEvaluator {
233+
// ... your evaluator
234+
}
177235
}
178236
----
179237
====
@@ -186,22 +244,22 @@ to:
186244
----
187245
@Bean
188246
static MethodSecurityExpressionHandler expressionHandler() {
189-
var expressionHandler = new DefaultMethodSecurityExpressionHandler();
190-
expressionHandler.setPermissionEvaluator(myPermissionEvaluator);
191-
return expressionHandler;
247+
var expressionHandler = new DefaultMethodSecurityExpressionHandler();
248+
expressionHandler.setPermissionEvaluator(myPermissionEvaluator);
249+
return expressionHandler;
192250
}
193251
----
194252
195253
.Kotlin
196254
[source,kotlin,role="secondary"]
197255
----
198256
companion object {
199-
@Bean
200-
fun expressionHandler(): MethodSecurityExpressionHandler {
201-
val expressionHandler = DefaultMethodSecurityExpressionHandler
202-
expressionHandler.setPermissionEvaluator(myPermissionEvaluator)
203-
return expressionHandler
204-
}
257+
@Bean
258+
fun expressionHandler(): MethodSecurityExpressionHandler {
259+
val expressionHandler = DefaultMethodSecurityExpressionHandler
260+
expressionHandler.setPermissionEvaluator(myPermissionEvaluator)
261+
return expressionHandler
262+
}
205263
}
206264
----
207265
====

0 commit comments

Comments
 (0)