Skip to content

Commit 4479cef

Browse files
committed
Default Require Explicit Session Management = true
Closes gh-11763
1 parent 0d58c51 commit 4479cef

File tree

20 files changed

+105
-39
lines changed

20 files changed

+105
-39
lines changed

config/src/main/java/org/springframework/security/config/annotation/web/configurers/SessionManagementConfigurer.java

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,9 @@
1818

1919
import java.util.ArrayList;
2020
import java.util.Arrays;
21+
import java.util.HashSet;
2122
import java.util.List;
23+
import java.util.Set;
2224

2325
import jakarta.servlet.http.HttpServletResponse;
2426
import jakarta.servlet.http.HttpSession;
@@ -135,7 +137,9 @@ public final class SessionManagementConfigurer<H extends HttpSecurityBuilder<H>>
135137

136138
private AuthenticationFailureHandler sessionAuthenticationFailureHandler;
137139

138-
private boolean requireExplicitAuthenticationStrategy;
140+
private Set<String> propertiesThatRequireImplicitAuthentication = new HashSet<>();
141+
142+
private Boolean requireExplicitAuthenticationStrategy;
139143

140144
/**
141145
* Creates a new instance
@@ -154,6 +158,7 @@ public SessionManagementConfigurer() {
154158
*/
155159
public SessionManagementConfigurer<H> invalidSessionUrl(String invalidSessionUrl) {
156160
this.invalidSessionUrl = invalidSessionUrl;
161+
this.propertiesThatRequireImplicitAuthentication.add("invalidSessionUrl = " + invalidSessionUrl);
157162
return this;
158163
}
159164

@@ -181,6 +186,7 @@ public SessionManagementConfigurer<H> requireExplicitAuthenticationStrategy(
181186
public SessionManagementConfigurer<H> invalidSessionStrategy(InvalidSessionStrategy invalidSessionStrategy) {
182187
Assert.notNull(invalidSessionStrategy, "invalidSessionStrategy");
183188
this.invalidSessionStrategy = invalidSessionStrategy;
189+
this.propertiesThatRequireImplicitAuthentication.add("invalidSessionStrategy = " + invalidSessionStrategy);
184190
return this;
185191
}
186192

@@ -195,6 +201,8 @@ public SessionManagementConfigurer<H> invalidSessionStrategy(InvalidSessionStrat
195201
*/
196202
public SessionManagementConfigurer<H> sessionAuthenticationErrorUrl(String sessionAuthenticationErrorUrl) {
197203
this.sessionAuthenticationErrorUrl = sessionAuthenticationErrorUrl;
204+
this.propertiesThatRequireImplicitAuthentication
205+
.add("sessionAuthenticationErrorUrl = " + sessionAuthenticationErrorUrl);
198206
return this;
199207
}
200208

@@ -210,6 +218,8 @@ public SessionManagementConfigurer<H> sessionAuthenticationErrorUrl(String sessi
210218
public SessionManagementConfigurer<H> sessionAuthenticationFailureHandler(
211219
AuthenticationFailureHandler sessionAuthenticationFailureHandler) {
212220
this.sessionAuthenticationFailureHandler = sessionAuthenticationFailureHandler;
221+
this.propertiesThatRequireImplicitAuthentication
222+
.add("sessionAuthenticationFailureHandler = " + sessionAuthenticationFailureHandler);
213223
return this;
214224
}
215225

@@ -245,6 +255,7 @@ public SessionManagementConfigurer<H> enableSessionUrlRewriting(boolean enableSe
245255
public SessionManagementConfigurer<H> sessionCreationPolicy(SessionCreationPolicy sessionCreationPolicy) {
246256
Assert.notNull(sessionCreationPolicy, "sessionCreationPolicy cannot be null");
247257
this.sessionPolicy = sessionCreationPolicy;
258+
this.propertiesThatRequireImplicitAuthentication.add("sessionCreationPolicy = " + sessionCreationPolicy);
248259
return this;
249260
}
250261

@@ -266,6 +277,8 @@ public SessionManagementConfigurer<H> sessionCreationPolicy(SessionCreationPolic
266277
public SessionManagementConfigurer<H> sessionAuthenticationStrategy(
267278
SessionAuthenticationStrategy sessionAuthenticationStrategy) {
268279
this.providedSessionAuthenticationStrategy = sessionAuthenticationStrategy;
280+
this.propertiesThatRequireImplicitAuthentication
281+
.add("sessionAuthenticationStrategy = " + sessionAuthenticationStrategy);
269282
return this;
270283
}
271284

@@ -309,6 +322,7 @@ public SessionManagementConfigurer<H> sessionFixation(
309322
*/
310323
public ConcurrencyControlConfigurer maximumSessions(int maximumSessions) {
311324
this.maximumSessions = maximumSessions;
325+
this.propertiesThatRequireImplicitAuthentication.add("maximumSessions = " + maximumSessions);
312326
return new ConcurrencyControlConfigurer();
313327
}
314328

@@ -384,8 +398,26 @@ public void configure(H http) {
384398
}
385399
}
386400

401+
private boolean shouldRequireExplicitAuthenticationStrategy() {
402+
boolean defaultRequireExplicitAuthenticationStrategy = this.propertiesThatRequireImplicitAuthentication
403+
.isEmpty();
404+
if (this.requireExplicitAuthenticationStrategy == null) {
405+
// explicit is not set, use default
406+
return defaultRequireExplicitAuthenticationStrategy;
407+
}
408+
if (this.requireExplicitAuthenticationStrategy && !defaultRequireExplicitAuthenticationStrategy) {
409+
// explicit disabled and implicit requires it
410+
throw new IllegalStateException(
411+
"Invalid configuration that explicitly sets requireExplicitAuthenticationStrategy to "
412+
+ this.requireExplicitAuthenticationStrategy
413+
+ " but implicitly requires it due to the following properties being set: "
414+
+ this.propertiesThatRequireImplicitAuthentication);
415+
}
416+
return this.requireExplicitAuthenticationStrategy;
417+
}
418+
387419
private SessionManagementFilter createSessionManagementFilter(H http) {
388-
if (this.requireExplicitAuthenticationStrategy) {
420+
if (shouldRequireExplicitAuthenticationStrategy()) {
389421
return null;
390422
}
391423
SecurityContextRepository securityContextRepository = http.getSharedObject(SecurityContextRepository.class);

config/src/main/java/org/springframework/security/config/http/HttpConfigurationBuilder.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -539,9 +539,10 @@ else if (StringUtils.hasText(invalidSessionStrategyRef)) {
539539
sessionMgmtFilter.addPropertyReference("invalidSessionStrategy", invalidSessionStrategyRef);
540540
}
541541
sessionMgmtFilter.addConstructorArgReference(sessionAuthStratRef);
542-
boolean registerSessionMgmtFilter = (sessionMgmtElt == null
543-
|| !"true".equals(sessionMgmtElt.getAttribute(ATT_AUTHENTICATION_STRATEGY_EXPLICIT_INVOCATION)));
544-
if (registerSessionMgmtFilter) {
542+
boolean registerSessionMgmtFilter = (sessionMgmtElt != null
543+
&& "false".equals(sessionMgmtElt.getAttribute(ATT_AUTHENTICATION_STRATEGY_EXPLICIT_INVOCATION)));
544+
if (registerSessionMgmtFilter || StringUtils.hasText(errorUrl) || StringUtils.hasText(invalidSessionUrl)
545+
|| StringUtils.hasText(invalidSessionStrategyRef)) {
545546
this.sfpf = (RootBeanDefinition) sessionMgmtFilter.getBeanDefinition();
546547
}
547548
this.sessionStrategyRef = new RuntimeBeanReference(sessionAuthStratRef);

config/src/test/java/org/springframework/security/config/annotation/web/configurers/DefaultFiltersTests.java

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,6 @@
5858
import org.springframework.security.web.header.HeaderWriterFilter;
5959
import org.springframework.security.web.savedrequest.RequestCacheAwareFilter;
6060
import org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter;
61-
import org.springframework.security.web.session.SessionManagementFilter;
6261
import org.springframework.security.web.util.matcher.AnyRequestMatcher;
6362

6463
import static org.assertj.core.api.Assertions.assertThat;
@@ -112,7 +111,6 @@ public void filterChainProxyBuilderIgnoringResources() {
112111
assertThat(classes.contains(RequestCacheAwareFilter.class)).isTrue();
113112
assertThat(classes.contains(SecurityContextHolderAwareRequestFilter.class)).isTrue();
114113
assertThat(classes.contains(AnonymousAuthenticationFilter.class)).isTrue();
115-
assertThat(classes.contains(SessionManagementFilter.class)).isTrue();
116114
assertThat(classes.contains(ExceptionTranslationFilter.class)).isTrue();
117115
assertThat(classes.contains(FilterSecurityInterceptor.class)).isTrue();
118116
}

config/src/test/java/org/springframework/security/config/annotation/web/configurers/NamespaceSessionManagementTests.java

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,17 @@ private static SessionResultMatcher session() {
258258
@EnableWebSecurity
259259
static class SessionManagementConfig extends WebSecurityConfigurerAdapter {
260260

261+
@Override
262+
protected void configure(HttpSecurity http) throws Exception {
263+
// @formatter:off
264+
super.configure(http);
265+
http
266+
.sessionManagement((sessions) -> sessions
267+
.requireExplicitAuthenticationStrategy(false)
268+
);
269+
// @formatter:on
270+
}
271+
261272
}
262273

263274
@Configuration
@@ -364,6 +375,7 @@ protected void configure(HttpSecurity http) throws Exception {
364375
// @formatter:off
365376
http
366377
.sessionManagement()
378+
.requireExplicitAuthenticationStrategy(false)
367379
.and()
368380
.httpBasic();
369381
// @formatter:on
@@ -379,8 +391,9 @@ static class SFPPostProcessedConfig extends WebSecurityConfigurerAdapter {
379391
protected void configure(HttpSecurity http) throws Exception {
380392
// @formatter:off
381393
http
382-
.sessionManagement()
383-
.and()
394+
.sessionManagement((sessions) -> sessions
395+
.requireExplicitAuthenticationStrategy(false)
396+
)
384397
.httpBasic();
385398
// @formatter:on
386399
}
@@ -400,9 +413,10 @@ static class SFPNewSessionSessionManagementConfig extends WebSecurityConfigurerA
400413
protected void configure(HttpSecurity http) throws Exception {
401414
// @formatter:off
402415
http
403-
.sessionManagement()
416+
.sessionManagement((sessions) -> sessions
404417
.sessionFixation().newSession()
405-
.and()
418+
.requireExplicitAuthenticationStrategy(false)
419+
)
406420
.httpBasic();
407421
// @formatter:on
408422
}

config/src/test/java/org/springframework/security/config/annotation/web/configurers/SessionManagementConfigurerTests.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -451,6 +451,7 @@ protected void configure(HttpSecurity http) throws Exception {
451451
http
452452
.sessionManagement((sessionManagement) ->
453453
sessionManagement
454+
.requireExplicitAuthenticationStrategy(false)
454455
.sessionFixation((sessionFixation) ->
455456
sessionFixation.newSession()
456457
)
@@ -583,9 +584,12 @@ static class SharedTrustResolverConfig extends WebSecurityConfigurerAdapter {
583584
static AuthenticationTrustResolver TR;
584585

585586
@Override
586-
protected void configure(HttpSecurity http) {
587+
protected void configure(HttpSecurity http) throws Exception {
587588
// @formatter:off
588589
http
590+
.sessionManagement((sessions) -> sessions
591+
.requireExplicitAuthenticationStrategy(false)
592+
)
589593
.setSharedObject(AuthenticationTrustResolver.class, TR);
590594
// @formatter:on
591595
}

config/src/test/java/org/springframework/security/config/http/DeferHttpSessionXmlConfigTests.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,8 @@ public void explicitDeferHttpSession() throws Exception {
6060

6161
this.springSecurityFilterChain.doFilter(mockRequest, response, chain);
6262

63+
verify(mockRequest, never()).isRequestedSessionIdValid();
64+
verify(mockRequest, never()).changeSessionId();
6365
verify(mockRequest, never()).getSession(anyBoolean());
6466
verify(mockRequest, never()).getSession();
6567
}

config/src/test/java/org/springframework/security/config/http/MiscHttpConfigTests.java

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,6 @@
106106
import org.springframework.security.web.savedrequest.RequestCacheAwareFilter;
107107
import org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter;
108108
import org.springframework.security.web.session.DisableEncodeUrlFilter;
109-
import org.springframework.security.web.session.SessionManagementFilter;
110109
import org.springframework.test.web.servlet.MockMvc;
111110
import org.springframework.test.web.servlet.MvcResult;
112111
import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
@@ -479,8 +478,6 @@ public void getWhenAuthenticatingThenConsultsCustomSecurityContextRepository() t
479478
.andReturn();
480479
// @formatter:on
481480
assertThat(result.getRequest().getSession(false)).isNotNull();
482-
verify(repository, atLeastOnce()).saveContext(any(SecurityContext.class), any(HttpServletRequest.class),
483-
any(HttpServletResponse.class));
484481
}
485482

486483
@Test
@@ -851,7 +848,6 @@ private void assertThatFiltersMatchExpectedAutoConfigList(String url) {
851848
assertThat(filters.next()).isInstanceOf(RequestCacheAwareFilter.class);
852849
assertThat(filters.next()).isInstanceOf(SecurityContextHolderAwareRequestFilter.class);
853850
assertThat(filters.next()).isInstanceOf(AnonymousAuthenticationFilter.class);
854-
assertThat(filters.next()).isInstanceOf(SessionManagementFilter.class);
855851
assertThat(filters.next()).isInstanceOf(ExceptionTranslationFilter.class);
856852
assertThat(filters.next()).isInstanceOf(FilterSecurityInterceptor.class)
857853
.hasFieldOrPropertyWithValue("observeOncePerRequest", false);

config/src/test/kotlin/org/springframework/security/config/annotation/web/session/SessionFixationDslTests.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ class SessionFixationDslTests {
7575
open fun securityFilterChain(http: HttpSecurity): SecurityFilterChain {
7676
http {
7777
sessionManagement {
78+
requireExplicitAuthenticationStrategy = false
7879
sessionFixation {
7980
newSession()
8081
}
@@ -111,6 +112,7 @@ class SessionFixationDslTests {
111112
open fun securityFilterChain(http: HttpSecurity): SecurityFilterChain {
112113
http {
113114
sessionManagement {
115+
requireExplicitAuthenticationStrategy = false
114116
sessionFixation {
115117
migrateSession()
116118
}
@@ -147,6 +149,7 @@ class SessionFixationDslTests {
147149
open fun securityFilterChain(http: HttpSecurity): SecurityFilterChain {
148150
http {
149151
sessionManagement {
152+
requireExplicitAuthenticationStrategy = false
150153
sessionFixation {
151154
changeSessionId()
152155
}

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

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@
2929
<http auto-config="true"
3030
use-authorization-manager="true">
3131
<intercept-url pattern="/**" access="permitAll"/>
32-
<session-management authentication-strategy-explicit-invocation="true"/>
3332
</http>
3433

3534
<b:import resource="CsrfConfigTests-shared-userservice.xml"/>

config/src/test/resources/org/springframework/security/config/http/SessionManagementConfigTests-ConcurrencyControlCustomLogoutHandler.xml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@
2525
https://www.springframework.org/schema/beans/spring-beans.xsd">
2626

2727
<http auto-config="true">
28-
<session-management>
28+
<session-management
29+
authentication-strategy-explicit-invocation="false">
2930
<concurrency-control/>
3031
</session-management>
3132
<remember-me services-ref="customRememberMeServices"/>

config/src/test/resources/org/springframework/security/config/http/SessionManagementConfigTests-ConcurrencyControlSessionRegistryAlias.xml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@
2525
https://www.springframework.org/schema/beans/spring-beans.xsd">
2626

2727
<http auto-config="true">
28-
<session-management>
28+
<session-management
29+
authentication-strategy-explicit-invocation="false">
2930
<concurrency-control session-registry-alias="sessionRegistry"/>
3031
</session-management>
3132
<csrf disabled="true"/>

config/src/test/resources/org/springframework/security/config/http/SessionManagementConfigTests-ConcurrencyControlSessionRegistryRef.xml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@
2525
https://www.springframework.org/schema/beans/spring-beans.xsd">
2626

2727
<http auto-config="true">
28-
<session-management>
28+
<session-management
29+
authentication-strategy-explicit-invocation="false">
2930
<concurrency-control session-registry-ref="sessionRegistry"/>
3031
</session-management>
3132
<csrf disabled="true"/>

config/src/test/resources/org/springframework/security/config/http/SessionManagementConfigTests-Sec1208.xml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,8 @@
2626

2727
<http auto-config="true" create-session="ifRequired" use-expressions="true">
2828
<intercept-url pattern="/auth/**" access="authenticated"/>
29-
<session-management>
29+
<session-management
30+
authentication-strategy-explicit-invocation="false">
3031
<concurrency-control max-sessions="1" error-if-maximum-exceeded="true"/>
3132
</session-management>
3233
<csrf disabled="true"/>

config/src/test/resources/org/springframework/security/config/http/SessionManagementConfigTests-SessionAuthenticationStrategyRef.xml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,9 @@
2626

2727
<http auto-config="true" use-expressions="true">
2828
<intercept-url pattern="/auth/**" access="authenticated"/>
29-
<session-management session-authentication-strategy-ref="teapotSessionAuthenticationStrategy"/>
29+
<session-management
30+
authentication-strategy-explicit-invocation="false"
31+
session-authentication-strategy-ref="teapotSessionAuthenticationStrategy"/>
3032
</http>
3133

3234
<b:bean name="basicController"

config/src/test/resources/org/springframework/security/config/http/SessionManagementConfigTests-SessionFixationProtectionMigrateSession.xml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,9 @@
2626

2727
<http auto-config="true" use-expressions="true">
2828
<intercept-url pattern="/auth/**" access="authenticated"/>
29-
<session-management session-fixation-protection="migrateSession"/>
29+
<session-management
30+
authentication-strategy-explicit-invocation="false"
31+
session-fixation-protection="migrateSession"/>
3032
</http>
3133

3234
<b:bean name="basicController"

test/src/test/java/org/springframework/security/test/web/servlet/showcase/login/AuthenticationTests.java

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,13 @@
2424
import org.springframework.context.annotation.Bean;
2525
import org.springframework.context.annotation.Configuration;
2626
import org.springframework.http.MediaType;
27+
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
2728
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
28-
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
2929
import org.springframework.security.core.userdetails.User;
3030
import org.springframework.security.core.userdetails.UserDetails;
3131
import org.springframework.security.core.userdetails.UserDetailsService;
3232
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
33+
import org.springframework.security.web.DefaultSecurityFilterChain;
3334
import org.springframework.test.context.ContextConfiguration;
3435
import org.springframework.test.context.junit.jupiter.SpringExtension;
3536
import org.springframework.test.context.web.WebAppConfiguration;
@@ -38,6 +39,7 @@
3839
import org.springframework.web.context.WebApplicationContext;
3940
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
4041

42+
import static org.springframework.security.config.Customizer.withDefaults;
4143
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestBuilders.formLogin;
4244
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.httpBasic;
4345
import static org.springframework.security.test.web.servlet.response.SecurityMockMvcResultMatchers.authenticated;
@@ -89,11 +91,26 @@ public void authenticationFailed() throws Exception {
8991
@Configuration
9092
@EnableWebSecurity
9193
@EnableWebMvc
92-
static class Config extends WebSecurityConfigurerAdapter {
94+
static class Config {
9395

94-
@Override
9596
@Bean
96-
public UserDetailsService userDetailsService() {
97+
DefaultSecurityFilterChain springSecurity(HttpSecurity http) throws Exception {
98+
// @formatter:off
99+
http
100+
.authorizeHttpRequests((requests) -> requests
101+
.anyRequest().authenticated()
102+
)
103+
.sessionManagement((sessions) -> sessions
104+
.requireExplicitAuthenticationStrategy(false)
105+
)
106+
.httpBasic(withDefaults())
107+
.formLogin(withDefaults());
108+
// @formatter:on
109+
return http.build();
110+
}
111+
112+
@Bean
113+
UserDetailsService userDetailsService() {
97114
// @formatter:off
98115
UserDetails user = User.withDefaultPasswordEncoder().username("user").password("password").roles("USER").build();
99116
return new InMemoryUserDetailsManager(user);

0 commit comments

Comments
 (0)