Default Require Explicit Session Management = true
Closes gh-11763
This commit is contained in:
parent
0d58c5180e
commit
4479cefade
|
@ -18,7 +18,9 @@ package org.springframework.security.config.annotation.web.configurers;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import jakarta.servlet.http.HttpServletResponse;
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
import jakarta.servlet.http.HttpSession;
|
import jakarta.servlet.http.HttpSession;
|
||||||
|
@ -135,7 +137,9 @@ public final class SessionManagementConfigurer<H extends HttpSecurityBuilder<H>>
|
||||||
|
|
||||||
private AuthenticationFailureHandler sessionAuthenticationFailureHandler;
|
private AuthenticationFailureHandler sessionAuthenticationFailureHandler;
|
||||||
|
|
||||||
private boolean requireExplicitAuthenticationStrategy;
|
private Set<String> propertiesThatRequireImplicitAuthentication = new HashSet<>();
|
||||||
|
|
||||||
|
private Boolean requireExplicitAuthenticationStrategy;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new instance
|
* Creates a new instance
|
||||||
|
@ -154,6 +158,7 @@ public final class SessionManagementConfigurer<H extends HttpSecurityBuilder<H>>
|
||||||
*/
|
*/
|
||||||
public SessionManagementConfigurer<H> invalidSessionUrl(String invalidSessionUrl) {
|
public SessionManagementConfigurer<H> invalidSessionUrl(String invalidSessionUrl) {
|
||||||
this.invalidSessionUrl = invalidSessionUrl;
|
this.invalidSessionUrl = invalidSessionUrl;
|
||||||
|
this.propertiesThatRequireImplicitAuthentication.add("invalidSessionUrl = " + invalidSessionUrl);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -181,6 +186,7 @@ public final class SessionManagementConfigurer<H extends HttpSecurityBuilder<H>>
|
||||||
public SessionManagementConfigurer<H> invalidSessionStrategy(InvalidSessionStrategy invalidSessionStrategy) {
|
public SessionManagementConfigurer<H> invalidSessionStrategy(InvalidSessionStrategy invalidSessionStrategy) {
|
||||||
Assert.notNull(invalidSessionStrategy, "invalidSessionStrategy");
|
Assert.notNull(invalidSessionStrategy, "invalidSessionStrategy");
|
||||||
this.invalidSessionStrategy = invalidSessionStrategy;
|
this.invalidSessionStrategy = invalidSessionStrategy;
|
||||||
|
this.propertiesThatRequireImplicitAuthentication.add("invalidSessionStrategy = " + invalidSessionStrategy);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -195,6 +201,8 @@ public final class SessionManagementConfigurer<H extends HttpSecurityBuilder<H>>
|
||||||
*/
|
*/
|
||||||
public SessionManagementConfigurer<H> sessionAuthenticationErrorUrl(String sessionAuthenticationErrorUrl) {
|
public SessionManagementConfigurer<H> sessionAuthenticationErrorUrl(String sessionAuthenticationErrorUrl) {
|
||||||
this.sessionAuthenticationErrorUrl = sessionAuthenticationErrorUrl;
|
this.sessionAuthenticationErrorUrl = sessionAuthenticationErrorUrl;
|
||||||
|
this.propertiesThatRequireImplicitAuthentication
|
||||||
|
.add("sessionAuthenticationErrorUrl = " + sessionAuthenticationErrorUrl);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -210,6 +218,8 @@ public final class SessionManagementConfigurer<H extends HttpSecurityBuilder<H>>
|
||||||
public SessionManagementConfigurer<H> sessionAuthenticationFailureHandler(
|
public SessionManagementConfigurer<H> sessionAuthenticationFailureHandler(
|
||||||
AuthenticationFailureHandler sessionAuthenticationFailureHandler) {
|
AuthenticationFailureHandler sessionAuthenticationFailureHandler) {
|
||||||
this.sessionAuthenticationFailureHandler = sessionAuthenticationFailureHandler;
|
this.sessionAuthenticationFailureHandler = sessionAuthenticationFailureHandler;
|
||||||
|
this.propertiesThatRequireImplicitAuthentication
|
||||||
|
.add("sessionAuthenticationFailureHandler = " + sessionAuthenticationFailureHandler);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -245,6 +255,7 @@ public final class SessionManagementConfigurer<H extends HttpSecurityBuilder<H>>
|
||||||
public SessionManagementConfigurer<H> sessionCreationPolicy(SessionCreationPolicy sessionCreationPolicy) {
|
public SessionManagementConfigurer<H> sessionCreationPolicy(SessionCreationPolicy sessionCreationPolicy) {
|
||||||
Assert.notNull(sessionCreationPolicy, "sessionCreationPolicy cannot be null");
|
Assert.notNull(sessionCreationPolicy, "sessionCreationPolicy cannot be null");
|
||||||
this.sessionPolicy = sessionCreationPolicy;
|
this.sessionPolicy = sessionCreationPolicy;
|
||||||
|
this.propertiesThatRequireImplicitAuthentication.add("sessionCreationPolicy = " + sessionCreationPolicy);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -266,6 +277,8 @@ public final class SessionManagementConfigurer<H extends HttpSecurityBuilder<H>>
|
||||||
public SessionManagementConfigurer<H> sessionAuthenticationStrategy(
|
public SessionManagementConfigurer<H> sessionAuthenticationStrategy(
|
||||||
SessionAuthenticationStrategy sessionAuthenticationStrategy) {
|
SessionAuthenticationStrategy sessionAuthenticationStrategy) {
|
||||||
this.providedSessionAuthenticationStrategy = sessionAuthenticationStrategy;
|
this.providedSessionAuthenticationStrategy = sessionAuthenticationStrategy;
|
||||||
|
this.propertiesThatRequireImplicitAuthentication
|
||||||
|
.add("sessionAuthenticationStrategy = " + sessionAuthenticationStrategy);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -309,6 +322,7 @@ public final class SessionManagementConfigurer<H extends HttpSecurityBuilder<H>>
|
||||||
*/
|
*/
|
||||||
public ConcurrencyControlConfigurer maximumSessions(int maximumSessions) {
|
public ConcurrencyControlConfigurer maximumSessions(int maximumSessions) {
|
||||||
this.maximumSessions = maximumSessions;
|
this.maximumSessions = maximumSessions;
|
||||||
|
this.propertiesThatRequireImplicitAuthentication.add("maximumSessions = " + maximumSessions);
|
||||||
return new ConcurrencyControlConfigurer();
|
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) {
|
private SessionManagementFilter createSessionManagementFilter(H http) {
|
||||||
if (this.requireExplicitAuthenticationStrategy) {
|
if (shouldRequireExplicitAuthenticationStrategy()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
SecurityContextRepository securityContextRepository = http.getSharedObject(SecurityContextRepository.class);
|
SecurityContextRepository securityContextRepository = http.getSharedObject(SecurityContextRepository.class);
|
||||||
|
|
|
@ -539,9 +539,10 @@ class HttpConfigurationBuilder {
|
||||||
sessionMgmtFilter.addPropertyReference("invalidSessionStrategy", invalidSessionStrategyRef);
|
sessionMgmtFilter.addPropertyReference("invalidSessionStrategy", invalidSessionStrategyRef);
|
||||||
}
|
}
|
||||||
sessionMgmtFilter.addConstructorArgReference(sessionAuthStratRef);
|
sessionMgmtFilter.addConstructorArgReference(sessionAuthStratRef);
|
||||||
boolean registerSessionMgmtFilter = (sessionMgmtElt == null
|
boolean registerSessionMgmtFilter = (sessionMgmtElt != null
|
||||||
|| !"true".equals(sessionMgmtElt.getAttribute(ATT_AUTHENTICATION_STRATEGY_EXPLICIT_INVOCATION)));
|
&& "false".equals(sessionMgmtElt.getAttribute(ATT_AUTHENTICATION_STRATEGY_EXPLICIT_INVOCATION)));
|
||||||
if (registerSessionMgmtFilter) {
|
if (registerSessionMgmtFilter || StringUtils.hasText(errorUrl) || StringUtils.hasText(invalidSessionUrl)
|
||||||
|
|| StringUtils.hasText(invalidSessionStrategyRef)) {
|
||||||
this.sfpf = (RootBeanDefinition) sessionMgmtFilter.getBeanDefinition();
|
this.sfpf = (RootBeanDefinition) sessionMgmtFilter.getBeanDefinition();
|
||||||
}
|
}
|
||||||
this.sessionStrategyRef = new RuntimeBeanReference(sessionAuthStratRef);
|
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.header.HeaderWriterFilter;
|
||||||
import org.springframework.security.web.savedrequest.RequestCacheAwareFilter;
|
import org.springframework.security.web.savedrequest.RequestCacheAwareFilter;
|
||||||
import org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter;
|
import org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter;
|
||||||
import org.springframework.security.web.session.SessionManagementFilter;
|
|
||||||
import org.springframework.security.web.util.matcher.AnyRequestMatcher;
|
import org.springframework.security.web.util.matcher.AnyRequestMatcher;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
@ -112,7 +111,6 @@ public class DefaultFiltersTests {
|
||||||
assertThat(classes.contains(RequestCacheAwareFilter.class)).isTrue();
|
assertThat(classes.contains(RequestCacheAwareFilter.class)).isTrue();
|
||||||
assertThat(classes.contains(SecurityContextHolderAwareRequestFilter.class)).isTrue();
|
assertThat(classes.contains(SecurityContextHolderAwareRequestFilter.class)).isTrue();
|
||||||
assertThat(classes.contains(AnonymousAuthenticationFilter.class)).isTrue();
|
assertThat(classes.contains(AnonymousAuthenticationFilter.class)).isTrue();
|
||||||
assertThat(classes.contains(SessionManagementFilter.class)).isTrue();
|
|
||||||
assertThat(classes.contains(ExceptionTranslationFilter.class)).isTrue();
|
assertThat(classes.contains(ExceptionTranslationFilter.class)).isTrue();
|
||||||
assertThat(classes.contains(FilterSecurityInterceptor.class)).isTrue();
|
assertThat(classes.contains(FilterSecurityInterceptor.class)).isTrue();
|
||||||
}
|
}
|
||||||
|
|
|
@ -258,6 +258,17 @@ public class NamespaceSessionManagementTests {
|
||||||
@EnableWebSecurity
|
@EnableWebSecurity
|
||||||
static class SessionManagementConfig extends WebSecurityConfigurerAdapter {
|
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
|
@Configuration
|
||||||
|
@ -364,6 +375,7 @@ public class NamespaceSessionManagementTests {
|
||||||
// @formatter:off
|
// @formatter:off
|
||||||
http
|
http
|
||||||
.sessionManagement()
|
.sessionManagement()
|
||||||
|
.requireExplicitAuthenticationStrategy(false)
|
||||||
.and()
|
.and()
|
||||||
.httpBasic();
|
.httpBasic();
|
||||||
// @formatter:on
|
// @formatter:on
|
||||||
|
@ -379,8 +391,9 @@ public class NamespaceSessionManagementTests {
|
||||||
protected void configure(HttpSecurity http) throws Exception {
|
protected void configure(HttpSecurity http) throws Exception {
|
||||||
// @formatter:off
|
// @formatter:off
|
||||||
http
|
http
|
||||||
.sessionManagement()
|
.sessionManagement((sessions) -> sessions
|
||||||
.and()
|
.requireExplicitAuthenticationStrategy(false)
|
||||||
|
)
|
||||||
.httpBasic();
|
.httpBasic();
|
||||||
// @formatter:on
|
// @formatter:on
|
||||||
}
|
}
|
||||||
|
@ -400,9 +413,10 @@ public class NamespaceSessionManagementTests {
|
||||||
protected void configure(HttpSecurity http) throws Exception {
|
protected void configure(HttpSecurity http) throws Exception {
|
||||||
// @formatter:off
|
// @formatter:off
|
||||||
http
|
http
|
||||||
.sessionManagement()
|
.sessionManagement((sessions) -> sessions
|
||||||
.sessionFixation().newSession()
|
.sessionFixation().newSession()
|
||||||
.and()
|
.requireExplicitAuthenticationStrategy(false)
|
||||||
|
)
|
||||||
.httpBasic();
|
.httpBasic();
|
||||||
// @formatter:on
|
// @formatter:on
|
||||||
}
|
}
|
||||||
|
|
|
@ -451,6 +451,7 @@ public class SessionManagementConfigurerTests {
|
||||||
http
|
http
|
||||||
.sessionManagement((sessionManagement) ->
|
.sessionManagement((sessionManagement) ->
|
||||||
sessionManagement
|
sessionManagement
|
||||||
|
.requireExplicitAuthenticationStrategy(false)
|
||||||
.sessionFixation((sessionFixation) ->
|
.sessionFixation((sessionFixation) ->
|
||||||
sessionFixation.newSession()
|
sessionFixation.newSession()
|
||||||
)
|
)
|
||||||
|
@ -583,9 +584,12 @@ public class SessionManagementConfigurerTests {
|
||||||
static AuthenticationTrustResolver TR;
|
static AuthenticationTrustResolver TR;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void configure(HttpSecurity http) {
|
protected void configure(HttpSecurity http) throws Exception {
|
||||||
// @formatter:off
|
// @formatter:off
|
||||||
http
|
http
|
||||||
|
.sessionManagement((sessions) -> sessions
|
||||||
|
.requireExplicitAuthenticationStrategy(false)
|
||||||
|
)
|
||||||
.setSharedObject(AuthenticationTrustResolver.class, TR);
|
.setSharedObject(AuthenticationTrustResolver.class, TR);
|
||||||
// @formatter:on
|
// @formatter:on
|
||||||
}
|
}
|
||||||
|
|
|
@ -60,6 +60,8 @@ public class DeferHttpSessionXmlConfigTests {
|
||||||
|
|
||||||
this.springSecurityFilterChain.doFilter(mockRequest, response, chain);
|
this.springSecurityFilterChain.doFilter(mockRequest, response, chain);
|
||||||
|
|
||||||
|
verify(mockRequest, never()).isRequestedSessionIdValid();
|
||||||
|
verify(mockRequest, never()).changeSessionId();
|
||||||
verify(mockRequest, never()).getSession(anyBoolean());
|
verify(mockRequest, never()).getSession(anyBoolean());
|
||||||
verify(mockRequest, never()).getSession();
|
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.savedrequest.RequestCacheAwareFilter;
|
||||||
import org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter;
|
import org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter;
|
||||||
import org.springframework.security.web.session.DisableEncodeUrlFilter;
|
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.MockMvc;
|
||||||
import org.springframework.test.web.servlet.MvcResult;
|
import org.springframework.test.web.servlet.MvcResult;
|
||||||
import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
|
import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
|
||||||
|
@ -479,8 +478,6 @@ public class MiscHttpConfigTests {
|
||||||
.andReturn();
|
.andReturn();
|
||||||
// @formatter:on
|
// @formatter:on
|
||||||
assertThat(result.getRequest().getSession(false)).isNotNull();
|
assertThat(result.getRequest().getSession(false)).isNotNull();
|
||||||
verify(repository, atLeastOnce()).saveContext(any(SecurityContext.class), any(HttpServletRequest.class),
|
|
||||||
any(HttpServletResponse.class));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -851,7 +848,6 @@ public class MiscHttpConfigTests {
|
||||||
assertThat(filters.next()).isInstanceOf(RequestCacheAwareFilter.class);
|
assertThat(filters.next()).isInstanceOf(RequestCacheAwareFilter.class);
|
||||||
assertThat(filters.next()).isInstanceOf(SecurityContextHolderAwareRequestFilter.class);
|
assertThat(filters.next()).isInstanceOf(SecurityContextHolderAwareRequestFilter.class);
|
||||||
assertThat(filters.next()).isInstanceOf(AnonymousAuthenticationFilter.class);
|
assertThat(filters.next()).isInstanceOf(AnonymousAuthenticationFilter.class);
|
||||||
assertThat(filters.next()).isInstanceOf(SessionManagementFilter.class);
|
|
||||||
assertThat(filters.next()).isInstanceOf(ExceptionTranslationFilter.class);
|
assertThat(filters.next()).isInstanceOf(ExceptionTranslationFilter.class);
|
||||||
assertThat(filters.next()).isInstanceOf(FilterSecurityInterceptor.class)
|
assertThat(filters.next()).isInstanceOf(FilterSecurityInterceptor.class)
|
||||||
.hasFieldOrPropertyWithValue("observeOncePerRequest", false);
|
.hasFieldOrPropertyWithValue("observeOncePerRequest", false);
|
||||||
|
|
|
@ -75,6 +75,7 @@ class SessionFixationDslTests {
|
||||||
open fun securityFilterChain(http: HttpSecurity): SecurityFilterChain {
|
open fun securityFilterChain(http: HttpSecurity): SecurityFilterChain {
|
||||||
http {
|
http {
|
||||||
sessionManagement {
|
sessionManagement {
|
||||||
|
requireExplicitAuthenticationStrategy = false
|
||||||
sessionFixation {
|
sessionFixation {
|
||||||
newSession()
|
newSession()
|
||||||
}
|
}
|
||||||
|
@ -111,6 +112,7 @@ class SessionFixationDslTests {
|
||||||
open fun securityFilterChain(http: HttpSecurity): SecurityFilterChain {
|
open fun securityFilterChain(http: HttpSecurity): SecurityFilterChain {
|
||||||
http {
|
http {
|
||||||
sessionManagement {
|
sessionManagement {
|
||||||
|
requireExplicitAuthenticationStrategy = false
|
||||||
sessionFixation {
|
sessionFixation {
|
||||||
migrateSession()
|
migrateSession()
|
||||||
}
|
}
|
||||||
|
@ -147,6 +149,7 @@ class SessionFixationDslTests {
|
||||||
open fun securityFilterChain(http: HttpSecurity): SecurityFilterChain {
|
open fun securityFilterChain(http: HttpSecurity): SecurityFilterChain {
|
||||||
http {
|
http {
|
||||||
sessionManagement {
|
sessionManagement {
|
||||||
|
requireExplicitAuthenticationStrategy = false
|
||||||
sessionFixation {
|
sessionFixation {
|
||||||
changeSessionId()
|
changeSessionId()
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,7 +29,6 @@
|
||||||
<http auto-config="true"
|
<http auto-config="true"
|
||||||
use-authorization-manager="true">
|
use-authorization-manager="true">
|
||||||
<intercept-url pattern="/**" access="permitAll"/>
|
<intercept-url pattern="/**" access="permitAll"/>
|
||||||
<session-management authentication-strategy-explicit-invocation="true"/>
|
|
||||||
</http>
|
</http>
|
||||||
|
|
||||||
<b:import resource="CsrfConfigTests-shared-userservice.xml"/>
|
<b:import resource="CsrfConfigTests-shared-userservice.xml"/>
|
||||||
|
|
|
@ -25,7 +25,8 @@
|
||||||
https://www.springframework.org/schema/beans/spring-beans.xsd">
|
https://www.springframework.org/schema/beans/spring-beans.xsd">
|
||||||
|
|
||||||
<http auto-config="true">
|
<http auto-config="true">
|
||||||
<session-management>
|
<session-management
|
||||||
|
authentication-strategy-explicit-invocation="false">
|
||||||
<concurrency-control/>
|
<concurrency-control/>
|
||||||
</session-management>
|
</session-management>
|
||||||
<remember-me services-ref="customRememberMeServices"/>
|
<remember-me services-ref="customRememberMeServices"/>
|
||||||
|
|
|
@ -25,7 +25,8 @@
|
||||||
https://www.springframework.org/schema/beans/spring-beans.xsd">
|
https://www.springframework.org/schema/beans/spring-beans.xsd">
|
||||||
|
|
||||||
<http auto-config="true">
|
<http auto-config="true">
|
||||||
<session-management>
|
<session-management
|
||||||
|
authentication-strategy-explicit-invocation="false">
|
||||||
<concurrency-control session-registry-alias="sessionRegistry"/>
|
<concurrency-control session-registry-alias="sessionRegistry"/>
|
||||||
</session-management>
|
</session-management>
|
||||||
<csrf disabled="true"/>
|
<csrf disabled="true"/>
|
||||||
|
|
|
@ -25,7 +25,8 @@
|
||||||
https://www.springframework.org/schema/beans/spring-beans.xsd">
|
https://www.springframework.org/schema/beans/spring-beans.xsd">
|
||||||
|
|
||||||
<http auto-config="true">
|
<http auto-config="true">
|
||||||
<session-management>
|
<session-management
|
||||||
|
authentication-strategy-explicit-invocation="false">
|
||||||
<concurrency-control session-registry-ref="sessionRegistry"/>
|
<concurrency-control session-registry-ref="sessionRegistry"/>
|
||||||
</session-management>
|
</session-management>
|
||||||
<csrf disabled="true"/>
|
<csrf disabled="true"/>
|
||||||
|
|
|
@ -26,7 +26,8 @@
|
||||||
|
|
||||||
<http auto-config="true" create-session="ifRequired" use-expressions="true">
|
<http auto-config="true" create-session="ifRequired" use-expressions="true">
|
||||||
<intercept-url pattern="/auth/**" access="authenticated"/>
|
<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"/>
|
<concurrency-control max-sessions="1" error-if-maximum-exceeded="true"/>
|
||||||
</session-management>
|
</session-management>
|
||||||
<csrf disabled="true"/>
|
<csrf disabled="true"/>
|
||||||
|
|
|
@ -26,7 +26,9 @@
|
||||||
|
|
||||||
<http auto-config="true" use-expressions="true">
|
<http auto-config="true" use-expressions="true">
|
||||||
<intercept-url pattern="/auth/**" access="authenticated"/>
|
<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>
|
</http>
|
||||||
|
|
||||||
<b:bean name="basicController"
|
<b:bean name="basicController"
|
||||||
|
|
|
@ -26,7 +26,9 @@
|
||||||
|
|
||||||
<http auto-config="true" use-expressions="true">
|
<http auto-config="true" use-expressions="true">
|
||||||
<intercept-url pattern="/auth/**" access="authenticated"/>
|
<intercept-url pattern="/auth/**" access="authenticated"/>
|
||||||
<session-management session-fixation-protection="migrateSession"/>
|
<session-management
|
||||||
|
authentication-strategy-explicit-invocation="false"
|
||||||
|
session-fixation-protection="migrateSession"/>
|
||||||
</http>
|
</http>
|
||||||
|
|
||||||
<b:bean name="basicController"
|
<b:bean name="basicController"
|
||||||
|
|
|
@ -24,12 +24,13 @@ import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.http.MediaType;
|
import org.springframework.http.MediaType;
|
||||||
|
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||||
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
|
||||||
import org.springframework.security.core.userdetails.User;
|
import org.springframework.security.core.userdetails.User;
|
||||||
import org.springframework.security.core.userdetails.UserDetails;
|
import org.springframework.security.core.userdetails.UserDetails;
|
||||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||||
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
|
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
|
||||||
|
import org.springframework.security.web.DefaultSecurityFilterChain;
|
||||||
import org.springframework.test.context.ContextConfiguration;
|
import org.springframework.test.context.ContextConfiguration;
|
||||||
import org.springframework.test.context.junit.jupiter.SpringExtension;
|
import org.springframework.test.context.junit.jupiter.SpringExtension;
|
||||||
import org.springframework.test.context.web.WebAppConfiguration;
|
import org.springframework.test.context.web.WebAppConfiguration;
|
||||||
|
@ -38,6 +39,7 @@ import org.springframework.test.web.servlet.setup.MockMvcBuilders;
|
||||||
import org.springframework.web.context.WebApplicationContext;
|
import org.springframework.web.context.WebApplicationContext;
|
||||||
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
|
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
|
||||||
|
|
||||||
|
import static org.springframework.security.config.Customizer.withDefaults;
|
||||||
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestBuilders.formLogin;
|
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestBuilders.formLogin;
|
||||||
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.httpBasic;
|
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.httpBasic;
|
||||||
import static org.springframework.security.test.web.servlet.response.SecurityMockMvcResultMatchers.authenticated;
|
import static org.springframework.security.test.web.servlet.response.SecurityMockMvcResultMatchers.authenticated;
|
||||||
|
@ -89,11 +91,26 @@ public class AuthenticationTests {
|
||||||
@Configuration
|
@Configuration
|
||||||
@EnableWebSecurity
|
@EnableWebSecurity
|
||||||
@EnableWebMvc
|
@EnableWebMvc
|
||||||
static class Config extends WebSecurityConfigurerAdapter {
|
static class Config {
|
||||||
|
|
||||||
@Override
|
|
||||||
@Bean
|
@Bean
|
||||||
public UserDetailsService userDetailsService() {
|
DefaultSecurityFilterChain springSecurity(HttpSecurity http) throws Exception {
|
||||||
|
// @formatter:off
|
||||||
|
http
|
||||||
|
.authorizeHttpRequests((requests) -> requests
|
||||||
|
.anyRequest().authenticated()
|
||||||
|
)
|
||||||
|
.sessionManagement((sessions) -> sessions
|
||||||
|
.requireExplicitAuthenticationStrategy(false)
|
||||||
|
)
|
||||||
|
.httpBasic(withDefaults())
|
||||||
|
.formLogin(withDefaults());
|
||||||
|
// @formatter:on
|
||||||
|
return http.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
UserDetailsService userDetailsService() {
|
||||||
// @formatter:off
|
// @formatter:off
|
||||||
UserDetails user = User.withDefaultPasswordEncoder().username("user").password("password").roles("USER").build();
|
UserDetails user = User.withDefaultPasswordEncoder().username("user").password("password").roles("USER").build();
|
||||||
return new InMemoryUserDetailsManager(user);
|
return new InMemoryUserDetailsManager(user);
|
||||||
|
|
|
@ -41,7 +41,7 @@ import org.springframework.security.web.WebAttributes;
|
||||||
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
|
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
|
||||||
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
|
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
|
||||||
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
|
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
|
||||||
import org.springframework.security.web.context.RequestAttributeSecurityContextRepository;
|
import org.springframework.security.web.context.HttpSessionSecurityContextRepository;
|
||||||
import org.springframework.security.web.context.SecurityContextRepository;
|
import org.springframework.security.web.context.SecurityContextRepository;
|
||||||
import org.springframework.security.web.util.matcher.RequestMatcher;
|
import org.springframework.security.web.util.matcher.RequestMatcher;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
@ -110,7 +110,7 @@ public abstract class AbstractPreAuthenticatedProcessingFilter extends GenericFi
|
||||||
|
|
||||||
private RequestMatcher requiresAuthenticationRequestMatcher = new PreAuthenticatedProcessingRequestMatcher();
|
private RequestMatcher requiresAuthenticationRequestMatcher = new PreAuthenticatedProcessingRequestMatcher();
|
||||||
|
|
||||||
private SecurityContextRepository securityContextRepository = new RequestAttributeSecurityContextRepository();
|
private SecurityContextRepository securityContextRepository = new HttpSessionSecurityContextRepository();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check whether all required properties have been set.
|
* Check whether all required properties have been set.
|
||||||
|
|
|
@ -37,7 +37,7 @@ import org.springframework.security.core.context.SecurityContextHolder;
|
||||||
import org.springframework.security.core.context.SecurityContextHolderStrategy;
|
import org.springframework.security.core.context.SecurityContextHolderStrategy;
|
||||||
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
|
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
|
||||||
import org.springframework.security.web.authentication.RememberMeServices;
|
import org.springframework.security.web.authentication.RememberMeServices;
|
||||||
import org.springframework.security.web.context.RequestAttributeSecurityContextRepository;
|
import org.springframework.security.web.context.HttpSessionSecurityContextRepository;
|
||||||
import org.springframework.security.web.context.SecurityContextRepository;
|
import org.springframework.security.web.context.SecurityContextRepository;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
import org.springframework.web.filter.GenericFilterBean;
|
import org.springframework.web.filter.GenericFilterBean;
|
||||||
|
@ -79,7 +79,7 @@ public class RememberMeAuthenticationFilter extends GenericFilterBean implements
|
||||||
|
|
||||||
private RememberMeServices rememberMeServices;
|
private RememberMeServices rememberMeServices;
|
||||||
|
|
||||||
private SecurityContextRepository securityContextRepository = new RequestAttributeSecurityContextRepository();
|
private SecurityContextRepository securityContextRepository = new HttpSessionSecurityContextRepository();
|
||||||
|
|
||||||
public RememberMeAuthenticationFilter(AuthenticationManager authenticationManager,
|
public RememberMeAuthenticationFilter(AuthenticationManager authenticationManager,
|
||||||
RememberMeServices rememberMeServices) {
|
RememberMeServices rememberMeServices) {
|
||||||
|
|
|
@ -40,7 +40,6 @@ import org.springframework.security.core.userdetails.User;
|
||||||
import org.springframework.security.web.WebAttributes;
|
import org.springframework.security.web.WebAttributes;
|
||||||
import org.springframework.security.web.authentication.ForwardAuthenticationFailureHandler;
|
import org.springframework.security.web.authentication.ForwardAuthenticationFailureHandler;
|
||||||
import org.springframework.security.web.authentication.ForwardAuthenticationSuccessHandler;
|
import org.springframework.security.web.authentication.ForwardAuthenticationSuccessHandler;
|
||||||
import org.springframework.security.web.context.RequestAttributeSecurityContextRepository;
|
|
||||||
import org.springframework.security.web.context.SecurityContextRepository;
|
import org.springframework.security.web.context.SecurityContextRepository;
|
||||||
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
|
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
|
||||||
|
|
||||||
|
@ -212,8 +211,6 @@ public class AbstractPreAuthenticatedProcessingFilterTests {
|
||||||
filter.doFilter(request, response, chain);
|
filter.doFilter(request, response, chain);
|
||||||
verify(am).authenticate(any(PreAuthenticatedAuthenticationToken.class));
|
verify(am).authenticate(any(PreAuthenticatedAuthenticationToken.class));
|
||||||
assertThat(response.getForwardedUrl()).isEqualTo("/forwardUrl");
|
assertThat(response.getForwardedUrl()).isEqualTo("/forwardUrl");
|
||||||
assertThat(request.getAttribute(RequestAttributeSecurityContextRepository.DEFAULT_REQUEST_ATTR_NAME))
|
|
||||||
.isNotNull();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
|
@ -35,7 +35,6 @@ import org.springframework.security.core.context.SecurityContextHolder;
|
||||||
import org.springframework.security.web.authentication.NullRememberMeServices;
|
import org.springframework.security.web.authentication.NullRememberMeServices;
|
||||||
import org.springframework.security.web.authentication.RememberMeServices;
|
import org.springframework.security.web.authentication.RememberMeServices;
|
||||||
import org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler;
|
import org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler;
|
||||||
import org.springframework.security.web.context.RequestAttributeSecurityContextRepository;
|
|
||||||
import org.springframework.security.web.context.SecurityContextRepository;
|
import org.springframework.security.web.context.SecurityContextRepository;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
@ -110,8 +109,6 @@ public class RememberMeAuthenticationFilterTests {
|
||||||
filter.doFilter(request, new MockHttpServletResponse(), fc);
|
filter.doFilter(request, new MockHttpServletResponse(), fc);
|
||||||
// Ensure filter setup with our remembered authentication object
|
// Ensure filter setup with our remembered authentication object
|
||||||
assertThat(SecurityContextHolder.getContext().getAuthentication()).isSameAs(this.remembered);
|
assertThat(SecurityContextHolder.getContext().getAuthentication()).isSameAs(this.remembered);
|
||||||
assertThat(request.getAttribute(RequestAttributeSecurityContextRepository.DEFAULT_REQUEST_ATTR_NAME))
|
|
||||||
.isNotNull();
|
|
||||||
verify(fc).doFilter(any(HttpServletRequest.class), any(HttpServletResponse.class));
|
verify(fc).doFilter(any(HttpServletRequest.class), any(HttpServletResponse.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -152,8 +149,6 @@ public class RememberMeAuthenticationFilterTests {
|
||||||
request.setRequestURI("x");
|
request.setRequestURI("x");
|
||||||
filter.doFilter(request, response, fc);
|
filter.doFilter(request, response, fc);
|
||||||
assertThat(response.getRedirectedUrl()).isEqualTo("/target");
|
assertThat(response.getRedirectedUrl()).isEqualTo("/target");
|
||||||
assertThat(request.getAttribute(RequestAttributeSecurityContextRepository.DEFAULT_REQUEST_ATTR_NAME))
|
|
||||||
.isNotNull();
|
|
||||||
// Should return after success handler is invoked, so chain should not proceed
|
// Should return after success handler is invoked, so chain should not proceed
|
||||||
verifyNoMoreInteractions(fc);
|
verifyNoMoreInteractions(fc);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue