1
0
mirror of synced 2026-05-22 21:33:16 +00:00

Default Require Explicit Session Management = true

Closes gh-11763
This commit is contained in:
Rob Winch
2022-09-30 15:06:29 -05:00
parent 0d58c5180e
commit 4479cefade
20 changed files with 105 additions and 39 deletions
@@ -18,7 +18,9 @@ package org.springframework.security.config.annotation.web.configurers;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
@@ -135,7 +137,9 @@ public final class SessionManagementConfigurer<H extends HttpSecurityBuilder<H>>
private AuthenticationFailureHandler sessionAuthenticationFailureHandler;
private boolean requireExplicitAuthenticationStrategy;
private Set<String> propertiesThatRequireImplicitAuthentication = new HashSet<>();
private Boolean requireExplicitAuthenticationStrategy;
/**
* Creates a new instance
@@ -154,6 +158,7 @@ public final class SessionManagementConfigurer<H extends HttpSecurityBuilder<H>>
*/
public SessionManagementConfigurer<H> invalidSessionUrl(String invalidSessionUrl) {
this.invalidSessionUrl = invalidSessionUrl;
this.propertiesThatRequireImplicitAuthentication.add("invalidSessionUrl = " + invalidSessionUrl);
return this;
}
@@ -181,6 +186,7 @@ public final class SessionManagementConfigurer<H extends HttpSecurityBuilder<H>>
public SessionManagementConfigurer<H> invalidSessionStrategy(InvalidSessionStrategy invalidSessionStrategy) {
Assert.notNull(invalidSessionStrategy, "invalidSessionStrategy");
this.invalidSessionStrategy = invalidSessionStrategy;
this.propertiesThatRequireImplicitAuthentication.add("invalidSessionStrategy = " + invalidSessionStrategy);
return this;
}
@@ -195,6 +201,8 @@ public final class SessionManagementConfigurer<H extends HttpSecurityBuilder<H>>
*/
public SessionManagementConfigurer<H> sessionAuthenticationErrorUrl(String sessionAuthenticationErrorUrl) {
this.sessionAuthenticationErrorUrl = sessionAuthenticationErrorUrl;
this.propertiesThatRequireImplicitAuthentication
.add("sessionAuthenticationErrorUrl = " + sessionAuthenticationErrorUrl);
return this;
}
@@ -210,6 +218,8 @@ public final class SessionManagementConfigurer<H extends HttpSecurityBuilder<H>>
public SessionManagementConfigurer<H> sessionAuthenticationFailureHandler(
AuthenticationFailureHandler sessionAuthenticationFailureHandler) {
this.sessionAuthenticationFailureHandler = sessionAuthenticationFailureHandler;
this.propertiesThatRequireImplicitAuthentication
.add("sessionAuthenticationFailureHandler = " + sessionAuthenticationFailureHandler);
return this;
}
@@ -245,6 +255,7 @@ public final class SessionManagementConfigurer<H extends HttpSecurityBuilder<H>>
public SessionManagementConfigurer<H> sessionCreationPolicy(SessionCreationPolicy sessionCreationPolicy) {
Assert.notNull(sessionCreationPolicy, "sessionCreationPolicy cannot be null");
this.sessionPolicy = sessionCreationPolicy;
this.propertiesThatRequireImplicitAuthentication.add("sessionCreationPolicy = " + sessionCreationPolicy);
return this;
}
@@ -266,6 +277,8 @@ public final class SessionManagementConfigurer<H extends HttpSecurityBuilder<H>>
public SessionManagementConfigurer<H> sessionAuthenticationStrategy(
SessionAuthenticationStrategy sessionAuthenticationStrategy) {
this.providedSessionAuthenticationStrategy = sessionAuthenticationStrategy;
this.propertiesThatRequireImplicitAuthentication
.add("sessionAuthenticationStrategy = " + sessionAuthenticationStrategy);
return this;
}
@@ -309,6 +322,7 @@ public final class SessionManagementConfigurer<H extends HttpSecurityBuilder<H>>
*/
public ConcurrencyControlConfigurer maximumSessions(int maximumSessions) {
this.maximumSessions = maximumSessions;
this.propertiesThatRequireImplicitAuthentication.add("maximumSessions = " + maximumSessions);
return new ConcurrencyControlConfigurer();
}
@@ -384,8 +398,26 @@ public final class SessionManagementConfigurer<H extends HttpSecurityBuilder<H>>
}
}
private boolean shouldRequireExplicitAuthenticationStrategy() {
boolean defaultRequireExplicitAuthenticationStrategy = this.propertiesThatRequireImplicitAuthentication
.isEmpty();
if (this.requireExplicitAuthenticationStrategy == null) {
// explicit is not set, use default
return defaultRequireExplicitAuthenticationStrategy;
}
if (this.requireExplicitAuthenticationStrategy && !defaultRequireExplicitAuthenticationStrategy) {
// explicit disabled and implicit requires it
throw new IllegalStateException(
"Invalid configuration that explicitly sets requireExplicitAuthenticationStrategy to "
+ this.requireExplicitAuthenticationStrategy
+ " but implicitly requires it due to the following properties being set: "
+ this.propertiesThatRequireImplicitAuthentication);
}
return this.requireExplicitAuthenticationStrategy;
}
private SessionManagementFilter createSessionManagementFilter(H http) {
if (this.requireExplicitAuthenticationStrategy) {
if (shouldRequireExplicitAuthenticationStrategy()) {
return null;
}
SecurityContextRepository securityContextRepository = http.getSharedObject(SecurityContextRepository.class);
@@ -539,9 +539,10 @@ class HttpConfigurationBuilder {
sessionMgmtFilter.addPropertyReference("invalidSessionStrategy", invalidSessionStrategyRef);
}
sessionMgmtFilter.addConstructorArgReference(sessionAuthStratRef);
boolean registerSessionMgmtFilter = (sessionMgmtElt == null
|| !"true".equals(sessionMgmtElt.getAttribute(ATT_AUTHENTICATION_STRATEGY_EXPLICIT_INVOCATION)));
if (registerSessionMgmtFilter) {
boolean registerSessionMgmtFilter = (sessionMgmtElt != null
&& "false".equals(sessionMgmtElt.getAttribute(ATT_AUTHENTICATION_STRATEGY_EXPLICIT_INVOCATION)));
if (registerSessionMgmtFilter || StringUtils.hasText(errorUrl) || StringUtils.hasText(invalidSessionUrl)
|| StringUtils.hasText(invalidSessionStrategyRef)) {
this.sfpf = (RootBeanDefinition) sessionMgmtFilter.getBeanDefinition();
}
this.sessionStrategyRef = new RuntimeBeanReference(sessionAuthStratRef);
@@ -58,7 +58,6 @@ import org.springframework.security.web.csrf.HttpSessionCsrfTokenRepository;
import org.springframework.security.web.header.HeaderWriterFilter;
import org.springframework.security.web.savedrequest.RequestCacheAwareFilter;
import org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter;
import org.springframework.security.web.session.SessionManagementFilter;
import org.springframework.security.web.util.matcher.AnyRequestMatcher;
import static org.assertj.core.api.Assertions.assertThat;
@@ -112,7 +111,6 @@ public class DefaultFiltersTests {
assertThat(classes.contains(RequestCacheAwareFilter.class)).isTrue();
assertThat(classes.contains(SecurityContextHolderAwareRequestFilter.class)).isTrue();
assertThat(classes.contains(AnonymousAuthenticationFilter.class)).isTrue();
assertThat(classes.contains(SessionManagementFilter.class)).isTrue();
assertThat(classes.contains(ExceptionTranslationFilter.class)).isTrue();
assertThat(classes.contains(FilterSecurityInterceptor.class)).isTrue();
}
@@ -258,6 +258,17 @@ public class NamespaceSessionManagementTests {
@EnableWebSecurity
static class SessionManagementConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
// @formatter:off
super.configure(http);
http
.sessionManagement((sessions) -> sessions
.requireExplicitAuthenticationStrategy(false)
);
// @formatter:on
}
}
@Configuration
@@ -364,6 +375,7 @@ public class NamespaceSessionManagementTests {
// @formatter:off
http
.sessionManagement()
.requireExplicitAuthenticationStrategy(false)
.and()
.httpBasic();
// @formatter:on
@@ -379,8 +391,9 @@ public class NamespaceSessionManagementTests {
protected void configure(HttpSecurity http) throws Exception {
// @formatter:off
http
.sessionManagement()
.and()
.sessionManagement((sessions) -> sessions
.requireExplicitAuthenticationStrategy(false)
)
.httpBasic();
// @formatter:on
}
@@ -400,9 +413,10 @@ public class NamespaceSessionManagementTests {
protected void configure(HttpSecurity http) throws Exception {
// @formatter:off
http
.sessionManagement()
.sessionManagement((sessions) -> sessions
.sessionFixation().newSession()
.and()
.requireExplicitAuthenticationStrategy(false)
)
.httpBasic();
// @formatter:on
}
@@ -451,6 +451,7 @@ public class SessionManagementConfigurerTests {
http
.sessionManagement((sessionManagement) ->
sessionManagement
.requireExplicitAuthenticationStrategy(false)
.sessionFixation((sessionFixation) ->
sessionFixation.newSession()
)
@@ -583,9 +584,12 @@ public class SessionManagementConfigurerTests {
static AuthenticationTrustResolver TR;
@Override
protected void configure(HttpSecurity http) {
protected void configure(HttpSecurity http) throws Exception {
// @formatter:off
http
.sessionManagement((sessions) -> sessions
.requireExplicitAuthenticationStrategy(false)
)
.setSharedObject(AuthenticationTrustResolver.class, TR);
// @formatter:on
}
@@ -60,6 +60,8 @@ public class DeferHttpSessionXmlConfigTests {
this.springSecurityFilterChain.doFilter(mockRequest, response, chain);
verify(mockRequest, never()).isRequestedSessionIdValid();
verify(mockRequest, never()).changeSessionId();
verify(mockRequest, never()).getSession(anyBoolean());
verify(mockRequest, never()).getSession();
}
@@ -106,7 +106,6 @@ import org.springframework.security.web.savedrequest.RequestCache;
import org.springframework.security.web.savedrequest.RequestCacheAwareFilter;
import org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter;
import org.springframework.security.web.session.DisableEncodeUrlFilter;
import org.springframework.security.web.session.SessionManagementFilter;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MvcResult;
import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
@@ -479,8 +478,6 @@ public class MiscHttpConfigTests {
.andReturn();
// @formatter:on
assertThat(result.getRequest().getSession(false)).isNotNull();
verify(repository, atLeastOnce()).saveContext(any(SecurityContext.class), any(HttpServletRequest.class),
any(HttpServletResponse.class));
}
@Test
@@ -851,7 +848,6 @@ public class MiscHttpConfigTests {
assertThat(filters.next()).isInstanceOf(RequestCacheAwareFilter.class);
assertThat(filters.next()).isInstanceOf(SecurityContextHolderAwareRequestFilter.class);
assertThat(filters.next()).isInstanceOf(AnonymousAuthenticationFilter.class);
assertThat(filters.next()).isInstanceOf(SessionManagementFilter.class);
assertThat(filters.next()).isInstanceOf(ExceptionTranslationFilter.class);
assertThat(filters.next()).isInstanceOf(FilterSecurityInterceptor.class)
.hasFieldOrPropertyWithValue("observeOncePerRequest", false);
@@ -75,6 +75,7 @@ class SessionFixationDslTests {
open fun securityFilterChain(http: HttpSecurity): SecurityFilterChain {
http {
sessionManagement {
requireExplicitAuthenticationStrategy = false
sessionFixation {
newSession()
}
@@ -111,6 +112,7 @@ class SessionFixationDslTests {
open fun securityFilterChain(http: HttpSecurity): SecurityFilterChain {
http {
sessionManagement {
requireExplicitAuthenticationStrategy = false
sessionFixation {
migrateSession()
}
@@ -147,6 +149,7 @@ class SessionFixationDslTests {
open fun securityFilterChain(http: HttpSecurity): SecurityFilterChain {
http {
sessionManagement {
requireExplicitAuthenticationStrategy = false
sessionFixation {
changeSessionId()
}
@@ -29,7 +29,6 @@
<http auto-config="true"
use-authorization-manager="true">
<intercept-url pattern="/**" access="permitAll"/>
<session-management authentication-strategy-explicit-invocation="true"/>
</http>
<b:import resource="CsrfConfigTests-shared-userservice.xml"/>
@@ -25,7 +25,8 @@
https://www.springframework.org/schema/beans/spring-beans.xsd">
<http auto-config="true">
<session-management>
<session-management
authentication-strategy-explicit-invocation="false">
<concurrency-control/>
</session-management>
<remember-me services-ref="customRememberMeServices"/>
@@ -25,7 +25,8 @@
https://www.springframework.org/schema/beans/spring-beans.xsd">
<http auto-config="true">
<session-management>
<session-management
authentication-strategy-explicit-invocation="false">
<concurrency-control session-registry-alias="sessionRegistry"/>
</session-management>
<csrf disabled="true"/>
@@ -25,7 +25,8 @@
https://www.springframework.org/schema/beans/spring-beans.xsd">
<http auto-config="true">
<session-management>
<session-management
authentication-strategy-explicit-invocation="false">
<concurrency-control session-registry-ref="sessionRegistry"/>
</session-management>
<csrf disabled="true"/>
@@ -26,7 +26,8 @@
<http auto-config="true" create-session="ifRequired" use-expressions="true">
<intercept-url pattern="/auth/**" access="authenticated"/>
<session-management>
<session-management
authentication-strategy-explicit-invocation="false">
<concurrency-control max-sessions="1" error-if-maximum-exceeded="true"/>
</session-management>
<csrf disabled="true"/>
@@ -26,7 +26,9 @@
<http auto-config="true" use-expressions="true">
<intercept-url pattern="/auth/**" access="authenticated"/>
<session-management session-authentication-strategy-ref="teapotSessionAuthenticationStrategy"/>
<session-management
authentication-strategy-explicit-invocation="false"
session-authentication-strategy-ref="teapotSessionAuthenticationStrategy"/>
</http>
<b:bean name="basicController"
@@ -26,7 +26,9 @@
<http auto-config="true" use-expressions="true">
<intercept-url pattern="/auth/**" access="authenticated"/>
<session-management session-fixation-protection="migrateSession"/>
<session-management
authentication-strategy-explicit-invocation="false"
session-fixation-protection="migrateSession"/>
</http>
<b:bean name="basicController"