Browse Source

SEC-2913: Post Process default session fixation AuthenticationStrategy

Before the default session fixation AuthenticationStrategy used a
NullEventPublisher when using the Java Configuration. This was due to the
fact that it is not exposed as a Bean and is not post processed.

We now post process the default session fixation AuthenticationStrategy
which initializes the EventPublisher properly.
Rob Winch 10 years ago
parent
commit
6c541468f6

+ 5 - 1
config/src/main/java/org/springframework/security/config/annotation/web/configurers/SessionManagementConfigurer.java

@@ -91,7 +91,8 @@ import org.springframework.util.Assert;
  */
 public final class SessionManagementConfigurer<H extends HttpSecurityBuilder<H>> extends
 		AbstractHttpConfigurer<SessionManagementConfigurer<H>, H> {
-	private SessionAuthenticationStrategy sessionFixationAuthenticationStrategy = createDefaultSessionFixationProtectionStrategy();
+	private final SessionAuthenticationStrategy DEFAULT_SESSION_FIXATION_STRATEGY = createDefaultSessionFixationProtectionStrategy();
+	private SessionAuthenticationStrategy sessionFixationAuthenticationStrategy = DEFAULT_SESSION_FIXATION_STRATEGY;
 	private SessionAuthenticationStrategy sessionAuthenticationStrategy;
 	private InvalidSessionStrategy invalidSessionStrategy;
 	private List<SessionAuthenticationStrategy> sessionAuthenticationStrategies = new ArrayList<SessionAuthenticationStrategy>();
@@ -475,6 +476,9 @@ public final class SessionManagementConfigurer<H extends HttpSecurityBuilder<H>>
 			return sessionAuthenticationStrategy;
 		}
 		List<SessionAuthenticationStrategy> delegateStrategies = sessionAuthenticationStrategies;
+		if(DEFAULT_SESSION_FIXATION_STRATEGY == sessionFixationAuthenticationStrategy) {
+			sessionFixationAuthenticationStrategy = postProcess(sessionFixationAuthenticationStrategy);
+		}
 		if (isConcurrentSessionControlEnabled()) {
 			SessionRegistry sessionRegistry = getSessionRegistry(http);
 			ConcurrentSessionControlAuthenticationStrategy concurrentSessionControlStrategy = new ConcurrentSessionControlAuthenticationStrategy(

+ 162 - 130
config/src/test/groovy/org/springframework/security/config/annotation/web/configurers/NamespaceSessionManagementTests.groovy

@@ -15,19 +15,19 @@
  */
 package org.springframework.security.config.annotation.web.configurers
 
-import org.springframework.context.annotation.Configuration
+import org.springframework.context.ApplicationListener
+import org.springframework.context.annotation.Bean
+import org.springframework.mock.web.MockHttpSession
+import org.springframework.security.authentication.TestingAuthenticationToken
 import org.springframework.security.config.annotation.BaseSpringSpec
-import org.springframework.security.config.annotation.ObjectPostProcessor
-import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
-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.WebSecurityConfigurerAdapter;
+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.WebSecurityConfigurerAdapter
 import org.springframework.security.core.session.SessionRegistry
-import org.springframework.security.web.authentication.session.NullAuthenticatedSessionStrategy;
-import org.springframework.security.web.authentication.session.SessionAuthenticationStrategy;
+import org.springframework.security.web.authentication.session.NullAuthenticatedSessionStrategy
+import org.springframework.security.web.authentication.session.SessionAuthenticationStrategy
+import org.springframework.security.web.authentication.session.SessionFixationProtectionEvent
 import org.springframework.security.web.authentication.session.SessionFixationProtectionStrategy
-import org.springframework.security.web.context.SecurityContextPersistenceFilter
-import org.springframework.security.web.context.SecurityContextRepository
 import org.springframework.security.web.session.ConcurrentSessionFilter
 import org.springframework.security.web.session.SessionManagementFilter
 
@@ -37,124 +37,156 @@ import org.springframework.security.web.session.SessionManagementFilter
  */
 class NamespaceSessionManagementTests extends BaseSpringSpec {
 
-    def "http/session-management"() {
-        when:
-            loadConfig(SessionManagementConfig)
-        then:
-            findSessionAuthenticationStrategy(SessionFixationProtectionStrategy)
-    }
-
-    @EnableWebSecurity
-    static class SessionManagementConfig extends WebSecurityConfigurerAdapter {
-        @Override
-        protected void configure(HttpSecurity http) throws Exception {
-            // enabled by default
-        }
-    }
-
-    def "http/session-management custom"() {
-        setup:
-            CustomSessionManagementConfig.SR = Mock(SessionRegistry)
-        when:
-            loadConfig(CustomSessionManagementConfig)
-            def concurrentStrategy = findFilter(SessionManagementFilter).sessionAuthenticationStrategy.delegateStrategies[0]
-        then:
-            findFilter(SessionManagementFilter).invalidSessionStrategy.destinationUrl == "/invalid-session"
-            findFilter(SessionManagementFilter).failureHandler.defaultFailureUrl == "/session-auth-error"
-            concurrentStrategy.maximumSessions == 1
-            concurrentStrategy.exceptionIfMaximumExceeded
-            concurrentStrategy.sessionRegistry == CustomSessionManagementConfig.SR
-            findFilter(ConcurrentSessionFilter).expiredUrl == "/expired-session"
-    }
-
-    @EnableWebSecurity
-    static class CustomSessionManagementConfig extends WebSecurityConfigurerAdapter {
-        static SessionRegistry SR
-        @Override
-        protected void configure(HttpSecurity http) throws Exception {
-            http
-                .sessionManagement()
-                    .invalidSessionUrl("/invalid-session") // session-management@invalid-session-url
-                    .sessionAuthenticationErrorUrl("/session-auth-error") // session-management@session-authentication-error-url
-                    .maximumSessions(1) // session-management/concurrency-control@max-sessions
-                        .maxSessionsPreventsLogin(true) // session-management/concurrency-control@error-if-maximum-exceeded
-                        .expiredUrl("/expired-session") // session-management/concurrency-control@expired-url
-                        .sessionRegistry(SR) // session-management/concurrency-control@session-registry-ref
-        }
-    }
-
-    def "http/session-management refs"() {
-        setup:
-            RefsSessionManagementConfig.SAS = Mock(SessionAuthenticationStrategy)
-        when:
-            loadConfig(RefsSessionManagementConfig)
-        then:
-            findFilter(SessionManagementFilter).sessionAuthenticationStrategy.delegateStrategies.find { it ==  RefsSessionManagementConfig.SAS }
-    }
-
-    @EnableWebSecurity
-    static class RefsSessionManagementConfig extends WebSecurityConfigurerAdapter {
-        static SessionAuthenticationStrategy SAS
-        @Override
-        protected void configure(HttpSecurity http) throws Exception {
-            http
-                .sessionManagement()
-                    .sessionAuthenticationStrategy(SAS) // session-management@session-authentication-strategy-ref
-        }
-    }
-
-    def "http/session-management@session-fixation-protection=none"() {
-        when:
-            loadConfig(SFPNoneSessionManagementConfig)
-        then:
-            findFilter(SessionManagementFilter).sessionAuthenticationStrategy.delegateStrategies.find { it instanceof  NullAuthenticatedSessionStrategy }
-    }
-
-    @EnableWebSecurity
-    static class SFPNoneSessionManagementConfig extends WebSecurityConfigurerAdapter {
-        @Override
-        protected void configure(HttpSecurity http) throws Exception {
-            http
-                .sessionManagement()
-                    .sessionAuthenticationStrategy(new NullAuthenticatedSessionStrategy())
-        }
-    }
-
-    def "http/session-management@session-fixation-protection=migrateSession (default)"() {
-        when:
-            loadConfig(SFPMigrateSessionManagementConfig)
-        then:
-            findSessionAuthenticationStrategy(SessionFixationProtectionStrategy).migrateSessionAttributes
-    }
-
-    @EnableWebSecurity
-    static class SFPMigrateSessionManagementConfig extends WebSecurityConfigurerAdapter {
-        @Override
-        protected void configure(HttpSecurity http) throws Exception {
-            http
-                .sessionManagement()
-        }
-    }
-
-    def "http/session-management@session-fixation-protection=newSession"() {
-        when:
-            loadConfig(SFPNewSessionSessionManagementConfig)
-        then:
-            !findSessionAuthenticationStrategy(SessionFixationProtectionStrategy).migrateSessionAttributes
-    }
-
-    def findSessionAuthenticationStrategy(def c) {
-        findFilter(SessionManagementFilter).sessionAuthenticationStrategy.delegateStrategies.find { it.class.isAssignableFrom(c) }
-    }
-
-    @EnableWebSecurity
-    static class SFPNewSessionSessionManagementConfig extends WebSecurityConfigurerAdapter {
-        @Override
-        protected void configure(HttpSecurity http) throws Exception {
-            http
-                .sessionManagement()
-                    .sessionFixation()
-                        .newSession()
-        }
-    }
+	def "http/session-management"() {
+		when:
+			loadConfig(SessionManagementConfig)
+		then:
+			findSessionAuthenticationStrategy(SessionFixationProtectionStrategy)
+	}
+
+	@EnableWebSecurity
+	static class SessionManagementConfig extends WebSecurityConfigurerAdapter {
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			// enabled by default
+		}
+	}
+
+	def "http/session-management custom"() {
+		setup:
+			CustomSessionManagementConfig.SR = Mock(SessionRegistry)
+		when:
+			loadConfig(CustomSessionManagementConfig)
+			def concurrentStrategy = findFilter(SessionManagementFilter).sessionAuthenticationStrategy.delegateStrategies[0]
+		then:
+			findFilter(SessionManagementFilter).invalidSessionStrategy.destinationUrl == "/invalid-session"
+			findFilter(SessionManagementFilter).failureHandler.defaultFailureUrl == "/session-auth-error"
+			concurrentStrategy.maximumSessions == 1
+			concurrentStrategy.exceptionIfMaximumExceeded
+			concurrentStrategy.sessionRegistry == CustomSessionManagementConfig.SR
+			findFilter(ConcurrentSessionFilter).expiredUrl == "/expired-session"
+	}
+
+	@EnableWebSecurity
+	static class CustomSessionManagementConfig extends WebSecurityConfigurerAdapter {
+		static SessionRegistry SR
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			http
+				.sessionManagement()
+					.invalidSessionUrl("/invalid-session") // session-management@invalid-session-url
+					.sessionAuthenticationErrorUrl("/session-auth-error") // session-management@session-authentication-error-url
+					.maximumSessions(1) // session-management/concurrency-control@max-sessions
+						.maxSessionsPreventsLogin(true) // session-management/concurrency-control@error-if-maximum-exceeded
+						.expiredUrl("/expired-session") // session-management/concurrency-control@expired-url
+						.sessionRegistry(SR) // session-management/concurrency-control@session-registry-ref
+		}
+	}
+
+	def "http/session-management refs"() {
+		setup:
+			RefsSessionManagementConfig.SAS = Mock(SessionAuthenticationStrategy)
+		when:
+			loadConfig(RefsSessionManagementConfig)
+		then:
+			findFilter(SessionManagementFilter).sessionAuthenticationStrategy.delegateStrategies.find { it ==  RefsSessionManagementConfig.SAS }
+	}
+
+	@EnableWebSecurity
+	static class RefsSessionManagementConfig extends WebSecurityConfigurerAdapter {
+		static SessionAuthenticationStrategy SAS
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			http
+				.sessionManagement()
+					.sessionAuthenticationStrategy(SAS) // session-management@session-authentication-strategy-ref
+		}
+	}
+
+	def "http/session-management@session-fixation-protection=none"() {
+		when:
+			loadConfig(SFPNoneSessionManagementConfig)
+		then:
+			findFilter(SessionManagementFilter).sessionAuthenticationStrategy.delegateStrategies.find { it instanceof  NullAuthenticatedSessionStrategy }
+	}
+
+	@EnableWebSecurity
+	static class SFPNoneSessionManagementConfig extends WebSecurityConfigurerAdapter {
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			http
+				.sessionManagement()
+					.sessionAuthenticationStrategy(new NullAuthenticatedSessionStrategy())
+		}
+	}
+
+	def "http/session-management@session-fixation-protection=migrateSession (default)"() {
+		when:
+			loadConfig(SFPMigrateSessionManagementConfig)
+		then:
+			findSessionAuthenticationStrategy(SessionFixationProtectionStrategy).migrateSessionAttributes
+	}
+
+	@EnableWebSecurity
+	static class SFPMigrateSessionManagementConfig extends WebSecurityConfigurerAdapter {
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			http
+				.sessionManagement()
+		}
+	}
+
+	def "http/session-management@session-fixation-protection=changeSessionId"() {
+		setup:
+			loadConfig(SFPPostProcessedConfig)
+		when:
+			findSessionAuthenticationStrategy(SessionFixationProtectionStrategy).onSessionChange("id", new MockHttpSession(), new TestingAuthenticationToken("u","p","ROLE_USER"))
+		then:
+			context.getBean(MockEventListener).events
+	}
+
+	@EnableWebSecurity
+	static class SFPPostProcessedConfig extends WebSecurityConfigurerAdapter {
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			http
+				.sessionManagement()
+		}
+
+		@Bean
+		public MockEventListener eventListener() {
+			new MockEventListener()
+		}
+	}
+
+	def "http/session-management@session-fixation-protection=newSession"() {
+		when:
+			loadConfig(SFPNewSessionSessionManagementConfig)
+		then:
+			!findSessionAuthenticationStrategy(SessionFixationProtectionStrategy).migrateSessionAttributes
+	}
+
+	def findSessionAuthenticationStrategy(def c) {
+		findFilter(SessionManagementFilter).sessionAuthenticationStrategy.delegateStrategies.find { it.class.isAssignableFrom(c) }
+	}
+
+	@EnableWebSecurity
+	static class SFPNewSessionSessionManagementConfig extends WebSecurityConfigurerAdapter {
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			http
+				.sessionManagement()
+					.sessionFixation()
+						.newSession()
+		}
+	}
+
+	static class MockEventListener implements ApplicationListener<SessionFixationProtectionEvent> {
+		List<SessionFixationProtectionEvent> events = []
+
+		public void onApplicationEvent(SessionFixationProtectionEvent event) {
+			events.add(event)
+		}
+
+	}
 }

+ 204 - 201
config/src/test/groovy/org/springframework/security/config/annotation/web/configurers/SessionManagementConfigurerTests.groovy

@@ -34,6 +34,7 @@ import org.springframework.security.web.access.ExceptionTranslationFilter
 import org.springframework.security.web.authentication.session.CompositeSessionAuthenticationStrategy
 import org.springframework.security.web.authentication.session.ConcurrentSessionControlAuthenticationStrategy
 import org.springframework.security.web.authentication.session.RegisterSessionAuthenticationStrategy
+import org.springframework.security.web.authentication.session.SessionFixationProtectionStrategy;
 import org.springframework.security.web.context.NullSecurityContextRepository
 import org.springframework.security.web.context.SecurityContextPersistenceFilter
 import org.springframework.security.web.context.SecurityContextRepository
@@ -48,205 +49,207 @@ import org.springframework.security.web.session.SessionManagementFilter
  */
 class SessionManagementConfigurerTests extends BaseSpringSpec {
 
-    def "sessionManagement does not override explicit RequestCache"() {
-        setup:
-            SessionManagementDoesNotOverrideExplicitRequestCacheConfig.REQUEST_CACHE = Mock(RequestCache)
-        when:
-            loadConfig(SessionManagementDoesNotOverrideExplicitRequestCacheConfig)
-        then:
-            findFilter(ExceptionTranslationFilter).requestCache == SessionManagementDoesNotOverrideExplicitRequestCacheConfig.REQUEST_CACHE
-    }
-
-    @EnableWebSecurity
-    static class SessionManagementDoesNotOverrideExplicitRequestCacheConfig extends WebSecurityConfigurerAdapter {
-        static RequestCache REQUEST_CACHE
-
-        @Override
-        protected void configure(HttpSecurity http) throws Exception {
-            http
-                .requestCache()
-                    .requestCache(REQUEST_CACHE)
-                    .and()
-                .sessionManagement()
-                    .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
-        }
-
-    }
-
-    def "sessionManagement does not override explict SecurityContextRepository"() {
-        setup:
-            SessionManagementDoesNotOverrideExplicitSecurityContextRepositoryConfig.SECURITY_CONTEXT_REPO = Mock(SecurityContextRepository)
-        when:
-            loadConfig(SessionManagementDoesNotOverrideExplicitSecurityContextRepositoryConfig)
-        then:
-            findFilter(SecurityContextPersistenceFilter).repo == SessionManagementDoesNotOverrideExplicitSecurityContextRepositoryConfig.SECURITY_CONTEXT_REPO
-    }
-
-    @EnableWebSecurity
-    static class SessionManagementDoesNotOverrideExplicitSecurityContextRepositoryConfig extends WebSecurityConfigurerAdapter {
-        static SecurityContextRepository SECURITY_CONTEXT_REPO
-
-        @Override
-        protected void configure(HttpSecurity http) throws Exception {
-            http
-                .securityContext()
-                    .securityContextRepository(SECURITY_CONTEXT_REPO)
-                    .and()
-                .sessionManagement()
-                    .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
-        }
-
-    }
-
-    def "invoke sessionManagement twice does not override"() {
-        when:
-            loadConfig(InvokeTwiceDoesNotOverride)
-        then:
-            findFilter(SecurityContextPersistenceFilter).repo.class == NullSecurityContextRepository
-    }
-
-    @EnableWebSecurity
-    static class InvokeTwiceDoesNotOverride extends WebSecurityConfigurerAdapter {
-        @Override
-        protected void configure(HttpSecurity http) throws Exception {
-            http
-                .sessionManagement()
-                    .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
-                    .and()
-                .sessionManagement()
-        }
-
-    }
-
-    def 'SEC-2137: disable session fixation and enable concurrency control'() {
-        setup: "context where session fixation is disabled and concurrency control is enabled"
-            loadConfig(DisableSessionFixationEnableConcurrencyControlConfig)
-            String originalSessionId = request.session.id
-            String credentials = "user:password"
-            request.addHeader("Authorization", "Basic " + credentials.bytes.encodeBase64())
-        when: "authenticate"
-            springSecurityFilterChain.doFilter(request, response, new MockFilterChain())
-        then: "session invalidate is not called"
-            request.session.id == originalSessionId
-    }
-
-    @EnableWebSecurity
-    static class DisableSessionFixationEnableConcurrencyControlConfig extends WebSecurityConfigurerAdapter {
-        @Override
-        public void configure(HttpSecurity http) {
-            http
-                .httpBasic()
-                    .and()
-                .sessionManagement()
-                    .sessionFixation().none()
-                    .maximumSessions(1)
-        }
-        @Override
-        protected void configure(AuthenticationManagerBuilder auth) {
-            auth
-                .inMemoryAuthentication()
-                    .withUser("user").password("password").roles("USER")
-        }
-    }
-
-    def 'session fixation and enable concurrency control'() {
-        setup: "context where session fixation is disabled and concurrency control is enabled"
-            loadConfig(ConcurrencyControlConfig)
-            def authenticatedSession
-        when: "authenticate successfully"
-            request.servletPath = "/login"
-            request.method = "POST"
-            request.setParameter("username", "user");
-            request.setParameter("password","password")
-            springSecurityFilterChain.doFilter(request, response, chain)
-            authenticatedSession = request.session
-        then: "authentication is sucessful"
-            response.status == HttpServletResponse.SC_MOVED_TEMPORARILY
-            response.redirectedUrl == "/"
-        when: "authenticate with the same user"
-            super.setup()
-            request.servletPath = "/login"
-            request.method = "POST"
-            request.setParameter("username", "user");
-            request.setParameter("password","password")
-            springSecurityFilterChain.doFilter(request, response, chain)
-        then:
-            response.status == HttpServletResponse.SC_MOVED_TEMPORARILY
-            response.redirectedUrl == '/login?error'
-        when: 'SEC-2574: When Session Expires and authentication attempted'
-            context.publishEvent(new HttpSessionDestroyedEvent(authenticatedSession))
-            super.setup()
-            request.servletPath = "/login"
-            request.method = "POST"
-            request.setParameter("username", "user");
-            request.setParameter("password","password")
-            springSecurityFilterChain.doFilter(request, response, chain)
-        then: "authentication is successful"
-            response.status == HttpServletResponse.SC_MOVED_TEMPORARILY
-            response.redirectedUrl == "/"
-    }
-
-    @EnableWebSecurity
-    static class ConcurrencyControlConfig extends WebSecurityConfigurerAdapter {
-        @Override
-        public void configure(HttpSecurity http) {
-            http
-                .formLogin()
-                    .and()
-                .sessionManagement()
-                    .maximumSessions(1)
-                        .maxSessionsPreventsLogin(true)
-        }
-        @Override
-        protected void configure(AuthenticationManagerBuilder auth) {
-            auth
-                .inMemoryAuthentication()
-                    .withUser("user").password("password").roles("USER")
-        }
-    }
-
-    def "sessionManagement ObjectPostProcessor"() {
-        setup:
-            AnyObjectPostProcessor opp = Mock()
-            HttpSecurity http = new HttpSecurity(opp, authenticationBldr, [:])
-        when:
-            http
-                .sessionManagement()
-                    .maximumSessions(1)
-                        .and()
-                    .and()
-                .build()
-
-        then: "SessionManagementFilter is registered with ObjectPostProcessor"
-            1 * opp.postProcess(_ as SessionManagementFilter) >> {SessionManagementFilter o -> o}
-        and: "ConcurrentSessionFilter is registered with ObjectPostProcessor"
-            1 * opp.postProcess(_ as ConcurrentSessionFilter) >> {ConcurrentSessionFilter o -> o}
-        and: "ConcurrentSessionControlAuthenticationStrategy is registered with ObjectPostProcessor"
-            1 * opp.postProcess(_ as ConcurrentSessionControlAuthenticationStrategy) >> {ConcurrentSessionControlAuthenticationStrategy o -> o}
-        and: "CompositeSessionAuthenticationStrategy is registered with ObjectPostProcessor"
-            1 * opp.postProcess(_ as CompositeSessionAuthenticationStrategy) >> {CompositeSessionAuthenticationStrategy o -> o}
-        and: "RegisterSessionAuthenticationStrategy is registered with ObjectPostProcessor"
-            1 * opp.postProcess(_ as RegisterSessionAuthenticationStrategy) >> {RegisterSessionAuthenticationStrategy o -> o}
-    }
-
-    def "use sharedObject trustResolver"() {
-        setup:
-            SharedTrustResolverConfig.TR = Mock(AuthenticationTrustResolver)
-        when:
-            loadConfig(SharedTrustResolverConfig)
-        then:
-            findFilter(SecurityContextPersistenceFilter).repo.trustResolver == SharedTrustResolverConfig.TR
-            findFilter(SessionManagementFilter).trustResolver == SharedTrustResolverConfig.TR
-    }
-
-    @EnableWebSecurity
-    static class SharedTrustResolverConfig extends WebSecurityConfigurerAdapter {
-        static AuthenticationTrustResolver TR
-
-        @Override
-        protected void configure(HttpSecurity http) throws Exception {
-            http
-                .setSharedObject(AuthenticationTrustResolver, TR)
-        }
-    }
+	def "sessionManagement does not override explicit RequestCache"() {
+		setup:
+			SessionManagementDoesNotOverrideExplicitRequestCacheConfig.REQUEST_CACHE = Mock(RequestCache)
+		when:
+			loadConfig(SessionManagementDoesNotOverrideExplicitRequestCacheConfig)
+		then:
+			findFilter(ExceptionTranslationFilter).requestCache == SessionManagementDoesNotOverrideExplicitRequestCacheConfig.REQUEST_CACHE
+	}
+
+	@EnableWebSecurity
+	static class SessionManagementDoesNotOverrideExplicitRequestCacheConfig extends WebSecurityConfigurerAdapter {
+		static RequestCache REQUEST_CACHE
+
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			http
+				.requestCache()
+					.requestCache(REQUEST_CACHE)
+					.and()
+				.sessionManagement()
+					.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
+		}
+
+	}
+
+	def "sessionManagement does not override explict SecurityContextRepository"() {
+		setup:
+			SessionManagementDoesNotOverrideExplicitSecurityContextRepositoryConfig.SECURITY_CONTEXT_REPO = Mock(SecurityContextRepository)
+		when:
+			loadConfig(SessionManagementDoesNotOverrideExplicitSecurityContextRepositoryConfig)
+		then:
+			findFilter(SecurityContextPersistenceFilter).repo == SessionManagementDoesNotOverrideExplicitSecurityContextRepositoryConfig.SECURITY_CONTEXT_REPO
+	}
+
+	@EnableWebSecurity
+	static class SessionManagementDoesNotOverrideExplicitSecurityContextRepositoryConfig extends WebSecurityConfigurerAdapter {
+		static SecurityContextRepository SECURITY_CONTEXT_REPO
+
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			http
+				.securityContext()
+					.securityContextRepository(SECURITY_CONTEXT_REPO)
+					.and()
+				.sessionManagement()
+					.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
+		}
+
+	}
+
+	def "invoke sessionManagement twice does not override"() {
+		when:
+			loadConfig(InvokeTwiceDoesNotOverride)
+		then:
+			findFilter(SecurityContextPersistenceFilter).repo.class == NullSecurityContextRepository
+	}
+
+	@EnableWebSecurity
+	static class InvokeTwiceDoesNotOverride extends WebSecurityConfigurerAdapter {
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			http
+				.sessionManagement()
+					.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
+					.and()
+				.sessionManagement()
+		}
+
+	}
+
+	def 'SEC-2137: disable session fixation and enable concurrency control'() {
+		setup: "context where session fixation is disabled and concurrency control is enabled"
+			loadConfig(DisableSessionFixationEnableConcurrencyControlConfig)
+			String originalSessionId = request.session.id
+			String credentials = "user:password"
+			request.addHeader("Authorization", "Basic " + credentials.bytes.encodeBase64())
+		when: "authenticate"
+			springSecurityFilterChain.doFilter(request, response, new MockFilterChain())
+		then: "session invalidate is not called"
+			request.session.id == originalSessionId
+	}
+
+	@EnableWebSecurity
+	static class DisableSessionFixationEnableConcurrencyControlConfig extends WebSecurityConfigurerAdapter {
+		@Override
+		public void configure(HttpSecurity http) {
+			http
+				.httpBasic()
+					.and()
+				.sessionManagement()
+					.sessionFixation().none()
+					.maximumSessions(1)
+		}
+		@Override
+		protected void configure(AuthenticationManagerBuilder auth) {
+			auth
+				.inMemoryAuthentication()
+					.withUser("user").password("password").roles("USER")
+		}
+	}
+
+	def 'session fixation and enable concurrency control'() {
+		setup: "context where session fixation is disabled and concurrency control is enabled"
+			loadConfig(ConcurrencyControlConfig)
+			def authenticatedSession
+		when: "authenticate successfully"
+			request.servletPath = "/login"
+			request.method = "POST"
+			request.setParameter("username", "user");
+			request.setParameter("password","password")
+			springSecurityFilterChain.doFilter(request, response, chain)
+			authenticatedSession = request.session
+		then: "authentication is sucessful"
+			response.status == HttpServletResponse.SC_MOVED_TEMPORARILY
+			response.redirectedUrl == "/"
+		when: "authenticate with the same user"
+			super.setup()
+			request.servletPath = "/login"
+			request.method = "POST"
+			request.setParameter("username", "user");
+			request.setParameter("password","password")
+			springSecurityFilterChain.doFilter(request, response, chain)
+		then:
+			response.status == HttpServletResponse.SC_MOVED_TEMPORARILY
+			response.redirectedUrl == '/login?error'
+		when: 'SEC-2574: When Session Expires and authentication attempted'
+			context.publishEvent(new HttpSessionDestroyedEvent(authenticatedSession))
+			super.setup()
+			request.servletPath = "/login"
+			request.method = "POST"
+			request.setParameter("username", "user");
+			request.setParameter("password","password")
+			springSecurityFilterChain.doFilter(request, response, chain)
+		then: "authentication is successful"
+			response.status == HttpServletResponse.SC_MOVED_TEMPORARILY
+			response.redirectedUrl == "/"
+	}
+
+	@EnableWebSecurity
+	static class ConcurrencyControlConfig extends WebSecurityConfigurerAdapter {
+		@Override
+		public void configure(HttpSecurity http) {
+			http
+				.formLogin()
+					.and()
+				.sessionManagement()
+					.maximumSessions(1)
+						.maxSessionsPreventsLogin(true)
+		}
+		@Override
+		protected void configure(AuthenticationManagerBuilder auth) {
+			auth
+				.inMemoryAuthentication()
+					.withUser("user").password("password").roles("USER")
+		}
+	}
+
+	def "sessionManagement ObjectPostProcessor"() {
+		setup:
+			AnyObjectPostProcessor opp = Mock()
+			HttpSecurity http = new HttpSecurity(opp, authenticationBldr, [:])
+		when:
+			http
+				.sessionManagement()
+					.maximumSessions(1)
+						.and()
+					.and()
+				.build()
+
+		then: "SessionManagementFilter is registered with ObjectPostProcessor"
+			1 * opp.postProcess(_ as SessionManagementFilter) >> {SessionManagementFilter o -> o}
+		and: "ConcurrentSessionFilter is registered with ObjectPostProcessor"
+			1 * opp.postProcess(_ as ConcurrentSessionFilter) >> {ConcurrentSessionFilter o -> o}
+		and: "ConcurrentSessionControlAuthenticationStrategy is registered with ObjectPostProcessor"
+			1 * opp.postProcess(_ as ConcurrentSessionControlAuthenticationStrategy) >> {ConcurrentSessionControlAuthenticationStrategy o -> o}
+		and: "CompositeSessionAuthenticationStrategy is registered with ObjectPostProcessor"
+			1 * opp.postProcess(_ as CompositeSessionAuthenticationStrategy) >> {CompositeSessionAuthenticationStrategy o -> o}
+		and: "RegisterSessionAuthenticationStrategy is registered with ObjectPostProcessor"
+			1 * opp.postProcess(_ as RegisterSessionAuthenticationStrategy) >> {RegisterSessionAuthenticationStrategy o -> o}
+		and: "SessionFixationProtectionStrategy is registered with ObjectPostProcessor"
+			1 * opp.postProcess(_ as SessionFixationProtectionStrategy) >> {SessionFixationProtectionStrategy o -> o}
+	}
+
+	def "use sharedObject trustResolver"() {
+		setup:
+			SharedTrustResolverConfig.TR = Mock(AuthenticationTrustResolver)
+		when:
+			loadConfig(SharedTrustResolverConfig)
+		then:
+			findFilter(SecurityContextPersistenceFilter).repo.trustResolver == SharedTrustResolverConfig.TR
+			findFilter(SessionManagementFilter).trustResolver == SharedTrustResolverConfig.TR
+	}
+
+	@EnableWebSecurity
+	static class SharedTrustResolverConfig extends WebSecurityConfigurerAdapter {
+		static AuthenticationTrustResolver TR
+
+		@Override
+		protected void configure(HttpSecurity http) throws Exception {
+			http
+				.setSharedObject(AuthenticationTrustResolver, TR)
+		}
+	}
 }