mirror of
https://github.com/spring-projects/spring-security.git
synced 2025-06-28 23:02:15 +00:00
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.
This commit is contained in:
parent
7b25b3e40d
commit
6c541468f6
@ -91,7 +91,8 @@ import org.springframework.util.Assert;
|
|||||||
*/
|
*/
|
||||||
public final class SessionManagementConfigurer<H extends HttpSecurityBuilder<H>> extends
|
public final class SessionManagementConfigurer<H extends HttpSecurityBuilder<H>> extends
|
||||||
AbstractHttpConfigurer<SessionManagementConfigurer<H>, H> {
|
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 SessionAuthenticationStrategy sessionAuthenticationStrategy;
|
||||||
private InvalidSessionStrategy invalidSessionStrategy;
|
private InvalidSessionStrategy invalidSessionStrategy;
|
||||||
private List<SessionAuthenticationStrategy> sessionAuthenticationStrategies = new ArrayList<SessionAuthenticationStrategy>();
|
private List<SessionAuthenticationStrategy> sessionAuthenticationStrategies = new ArrayList<SessionAuthenticationStrategy>();
|
||||||
@ -475,6 +476,9 @@ public final class SessionManagementConfigurer<H extends HttpSecurityBuilder<H>>
|
|||||||
return sessionAuthenticationStrategy;
|
return sessionAuthenticationStrategy;
|
||||||
}
|
}
|
||||||
List<SessionAuthenticationStrategy> delegateStrategies = sessionAuthenticationStrategies;
|
List<SessionAuthenticationStrategy> delegateStrategies = sessionAuthenticationStrategies;
|
||||||
|
if(DEFAULT_SESSION_FIXATION_STRATEGY == sessionFixationAuthenticationStrategy) {
|
||||||
|
sessionFixationAuthenticationStrategy = postProcess(sessionFixationAuthenticationStrategy);
|
||||||
|
}
|
||||||
if (isConcurrentSessionControlEnabled()) {
|
if (isConcurrentSessionControlEnabled()) {
|
||||||
SessionRegistry sessionRegistry = getSessionRegistry(http);
|
SessionRegistry sessionRegistry = getSessionRegistry(http);
|
||||||
ConcurrentSessionControlAuthenticationStrategy concurrentSessionControlStrategy = new ConcurrentSessionControlAuthenticationStrategy(
|
ConcurrentSessionControlAuthenticationStrategy concurrentSessionControlStrategy = new ConcurrentSessionControlAuthenticationStrategy(
|
||||||
|
@ -15,19 +15,19 @@
|
|||||||
*/
|
*/
|
||||||
package org.springframework.security.config.annotation.web.configurers
|
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.BaseSpringSpec
|
||||||
import org.springframework.security.config.annotation.ObjectPostProcessor
|
import org.springframework.security.config.annotation.web.builders.HttpSecurity
|
||||||
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
|
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity
|
||||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter
|
||||||
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.core.session.SessionRegistry
|
||||||
import org.springframework.security.web.authentication.session.NullAuthenticatedSessionStrategy;
|
import org.springframework.security.web.authentication.session.NullAuthenticatedSessionStrategy
|
||||||
import org.springframework.security.web.authentication.session.SessionAuthenticationStrategy;
|
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.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.ConcurrentSessionFilter
|
||||||
import org.springframework.security.web.session.SessionManagementFilter
|
import org.springframework.security.web.session.SessionManagementFilter
|
||||||
|
|
||||||
@ -37,124 +37,156 @@ import org.springframework.security.web.session.SessionManagementFilter
|
|||||||
*/
|
*/
|
||||||
class NamespaceSessionManagementTests extends BaseSpringSpec {
|
class NamespaceSessionManagementTests extends BaseSpringSpec {
|
||||||
|
|
||||||
def "http/session-management"() {
|
def "http/session-management"() {
|
||||||
when:
|
when:
|
||||||
loadConfig(SessionManagementConfig)
|
loadConfig(SessionManagementConfig)
|
||||||
then:
|
then:
|
||||||
findSessionAuthenticationStrategy(SessionFixationProtectionStrategy)
|
findSessionAuthenticationStrategy(SessionFixationProtectionStrategy)
|
||||||
}
|
}
|
||||||
|
|
||||||
@EnableWebSecurity
|
@EnableWebSecurity
|
||||||
static class SessionManagementConfig extends WebSecurityConfigurerAdapter {
|
static class SessionManagementConfig extends WebSecurityConfigurerAdapter {
|
||||||
@Override
|
@Override
|
||||||
protected void configure(HttpSecurity http) throws Exception {
|
protected void configure(HttpSecurity http) throws Exception {
|
||||||
// enabled by default
|
// enabled by default
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
def "http/session-management custom"() {
|
def "http/session-management custom"() {
|
||||||
setup:
|
setup:
|
||||||
CustomSessionManagementConfig.SR = Mock(SessionRegistry)
|
CustomSessionManagementConfig.SR = Mock(SessionRegistry)
|
||||||
when:
|
when:
|
||||||
loadConfig(CustomSessionManagementConfig)
|
loadConfig(CustomSessionManagementConfig)
|
||||||
def concurrentStrategy = findFilter(SessionManagementFilter).sessionAuthenticationStrategy.delegateStrategies[0]
|
def concurrentStrategy = findFilter(SessionManagementFilter).sessionAuthenticationStrategy.delegateStrategies[0]
|
||||||
then:
|
then:
|
||||||
findFilter(SessionManagementFilter).invalidSessionStrategy.destinationUrl == "/invalid-session"
|
findFilter(SessionManagementFilter).invalidSessionStrategy.destinationUrl == "/invalid-session"
|
||||||
findFilter(SessionManagementFilter).failureHandler.defaultFailureUrl == "/session-auth-error"
|
findFilter(SessionManagementFilter).failureHandler.defaultFailureUrl == "/session-auth-error"
|
||||||
concurrentStrategy.maximumSessions == 1
|
concurrentStrategy.maximumSessions == 1
|
||||||
concurrentStrategy.exceptionIfMaximumExceeded
|
concurrentStrategy.exceptionIfMaximumExceeded
|
||||||
concurrentStrategy.sessionRegistry == CustomSessionManagementConfig.SR
|
concurrentStrategy.sessionRegistry == CustomSessionManagementConfig.SR
|
||||||
findFilter(ConcurrentSessionFilter).expiredUrl == "/expired-session"
|
findFilter(ConcurrentSessionFilter).expiredUrl == "/expired-session"
|
||||||
}
|
}
|
||||||
|
|
||||||
@EnableWebSecurity
|
@EnableWebSecurity
|
||||||
static class CustomSessionManagementConfig extends WebSecurityConfigurerAdapter {
|
static class CustomSessionManagementConfig extends WebSecurityConfigurerAdapter {
|
||||||
static SessionRegistry SR
|
static SessionRegistry SR
|
||||||
@Override
|
@Override
|
||||||
protected void configure(HttpSecurity http) throws Exception {
|
protected void configure(HttpSecurity http) throws Exception {
|
||||||
http
|
http
|
||||||
.sessionManagement()
|
.sessionManagement()
|
||||||
.invalidSessionUrl("/invalid-session") // session-management@invalid-session-url
|
.invalidSessionUrl("/invalid-session") // session-management@invalid-session-url
|
||||||
.sessionAuthenticationErrorUrl("/session-auth-error") // session-management@session-authentication-error-url
|
.sessionAuthenticationErrorUrl("/session-auth-error") // session-management@session-authentication-error-url
|
||||||
.maximumSessions(1) // session-management/concurrency-control@max-sessions
|
.maximumSessions(1) // session-management/concurrency-control@max-sessions
|
||||||
.maxSessionsPreventsLogin(true) // session-management/concurrency-control@error-if-maximum-exceeded
|
.maxSessionsPreventsLogin(true) // session-management/concurrency-control@error-if-maximum-exceeded
|
||||||
.expiredUrl("/expired-session") // session-management/concurrency-control@expired-url
|
.expiredUrl("/expired-session") // session-management/concurrency-control@expired-url
|
||||||
.sessionRegistry(SR) // session-management/concurrency-control@session-registry-ref
|
.sessionRegistry(SR) // session-management/concurrency-control@session-registry-ref
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
def "http/session-management refs"() {
|
def "http/session-management refs"() {
|
||||||
setup:
|
setup:
|
||||||
RefsSessionManagementConfig.SAS = Mock(SessionAuthenticationStrategy)
|
RefsSessionManagementConfig.SAS = Mock(SessionAuthenticationStrategy)
|
||||||
when:
|
when:
|
||||||
loadConfig(RefsSessionManagementConfig)
|
loadConfig(RefsSessionManagementConfig)
|
||||||
then:
|
then:
|
||||||
findFilter(SessionManagementFilter).sessionAuthenticationStrategy.delegateStrategies.find { it == RefsSessionManagementConfig.SAS }
|
findFilter(SessionManagementFilter).sessionAuthenticationStrategy.delegateStrategies.find { it == RefsSessionManagementConfig.SAS }
|
||||||
}
|
}
|
||||||
|
|
||||||
@EnableWebSecurity
|
@EnableWebSecurity
|
||||||
static class RefsSessionManagementConfig extends WebSecurityConfigurerAdapter {
|
static class RefsSessionManagementConfig extends WebSecurityConfigurerAdapter {
|
||||||
static SessionAuthenticationStrategy SAS
|
static SessionAuthenticationStrategy SAS
|
||||||
@Override
|
@Override
|
||||||
protected void configure(HttpSecurity http) throws Exception {
|
protected void configure(HttpSecurity http) throws Exception {
|
||||||
http
|
http
|
||||||
.sessionManagement()
|
.sessionManagement()
|
||||||
.sessionAuthenticationStrategy(SAS) // session-management@session-authentication-strategy-ref
|
.sessionAuthenticationStrategy(SAS) // session-management@session-authentication-strategy-ref
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
def "http/session-management@session-fixation-protection=none"() {
|
def "http/session-management@session-fixation-protection=none"() {
|
||||||
when:
|
when:
|
||||||
loadConfig(SFPNoneSessionManagementConfig)
|
loadConfig(SFPNoneSessionManagementConfig)
|
||||||
then:
|
then:
|
||||||
findFilter(SessionManagementFilter).sessionAuthenticationStrategy.delegateStrategies.find { it instanceof NullAuthenticatedSessionStrategy }
|
findFilter(SessionManagementFilter).sessionAuthenticationStrategy.delegateStrategies.find { it instanceof NullAuthenticatedSessionStrategy }
|
||||||
}
|
}
|
||||||
|
|
||||||
@EnableWebSecurity
|
@EnableWebSecurity
|
||||||
static class SFPNoneSessionManagementConfig extends WebSecurityConfigurerAdapter {
|
static class SFPNoneSessionManagementConfig extends WebSecurityConfigurerAdapter {
|
||||||
@Override
|
@Override
|
||||||
protected void configure(HttpSecurity http) throws Exception {
|
protected void configure(HttpSecurity http) throws Exception {
|
||||||
http
|
http
|
||||||
.sessionManagement()
|
.sessionManagement()
|
||||||
.sessionAuthenticationStrategy(new NullAuthenticatedSessionStrategy())
|
.sessionAuthenticationStrategy(new NullAuthenticatedSessionStrategy())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
def "http/session-management@session-fixation-protection=migrateSession (default)"() {
|
def "http/session-management@session-fixation-protection=migrateSession (default)"() {
|
||||||
when:
|
when:
|
||||||
loadConfig(SFPMigrateSessionManagementConfig)
|
loadConfig(SFPMigrateSessionManagementConfig)
|
||||||
then:
|
then:
|
||||||
findSessionAuthenticationStrategy(SessionFixationProtectionStrategy).migrateSessionAttributes
|
findSessionAuthenticationStrategy(SessionFixationProtectionStrategy).migrateSessionAttributes
|
||||||
}
|
}
|
||||||
|
|
||||||
@EnableWebSecurity
|
@EnableWebSecurity
|
||||||
static class SFPMigrateSessionManagementConfig extends WebSecurityConfigurerAdapter {
|
static class SFPMigrateSessionManagementConfig extends WebSecurityConfigurerAdapter {
|
||||||
@Override
|
@Override
|
||||||
protected void configure(HttpSecurity http) throws Exception {
|
protected void configure(HttpSecurity http) throws Exception {
|
||||||
http
|
http
|
||||||
.sessionManagement()
|
.sessionManagement()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
def "http/session-management@session-fixation-protection=newSession"() {
|
def "http/session-management@session-fixation-protection=changeSessionId"() {
|
||||||
when:
|
setup:
|
||||||
loadConfig(SFPNewSessionSessionManagementConfig)
|
loadConfig(SFPPostProcessedConfig)
|
||||||
then:
|
when:
|
||||||
!findSessionAuthenticationStrategy(SessionFixationProtectionStrategy).migrateSessionAttributes
|
findSessionAuthenticationStrategy(SessionFixationProtectionStrategy).onSessionChange("id", new MockHttpSession(), new TestingAuthenticationToken("u","p","ROLE_USER"))
|
||||||
}
|
then:
|
||||||
|
context.getBean(MockEventListener).events
|
||||||
|
}
|
||||||
|
|
||||||
def findSessionAuthenticationStrategy(def c) {
|
@EnableWebSecurity
|
||||||
findFilter(SessionManagementFilter).sessionAuthenticationStrategy.delegateStrategies.find { it.class.isAssignableFrom(c) }
|
static class SFPPostProcessedConfig extends WebSecurityConfigurerAdapter {
|
||||||
}
|
@Override
|
||||||
|
protected void configure(HttpSecurity http) throws Exception {
|
||||||
|
http
|
||||||
|
.sessionManagement()
|
||||||
|
}
|
||||||
|
|
||||||
@EnableWebSecurity
|
@Bean
|
||||||
static class SFPNewSessionSessionManagementConfig extends WebSecurityConfigurerAdapter {
|
public MockEventListener eventListener() {
|
||||||
@Override
|
new MockEventListener()
|
||||||
protected void configure(HttpSecurity http) throws Exception {
|
}
|
||||||
http
|
}
|
||||||
.sessionManagement()
|
|
||||||
.sessionFixation()
|
def "http/session-management@session-fixation-protection=newSession"() {
|
||||||
.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)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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.CompositeSessionAuthenticationStrategy
|
||||||
import org.springframework.security.web.authentication.session.ConcurrentSessionControlAuthenticationStrategy
|
import org.springframework.security.web.authentication.session.ConcurrentSessionControlAuthenticationStrategy
|
||||||
import org.springframework.security.web.authentication.session.RegisterSessionAuthenticationStrategy
|
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.NullSecurityContextRepository
|
||||||
import org.springframework.security.web.context.SecurityContextPersistenceFilter
|
import org.springframework.security.web.context.SecurityContextPersistenceFilter
|
||||||
import org.springframework.security.web.context.SecurityContextRepository
|
import org.springframework.security.web.context.SecurityContextRepository
|
||||||
@ -48,205 +49,207 @@ import org.springframework.security.web.session.SessionManagementFilter
|
|||||||
*/
|
*/
|
||||||
class SessionManagementConfigurerTests extends BaseSpringSpec {
|
class SessionManagementConfigurerTests extends BaseSpringSpec {
|
||||||
|
|
||||||
def "sessionManagement does not override explicit RequestCache"() {
|
def "sessionManagement does not override explicit RequestCache"() {
|
||||||
setup:
|
setup:
|
||||||
SessionManagementDoesNotOverrideExplicitRequestCacheConfig.REQUEST_CACHE = Mock(RequestCache)
|
SessionManagementDoesNotOverrideExplicitRequestCacheConfig.REQUEST_CACHE = Mock(RequestCache)
|
||||||
when:
|
when:
|
||||||
loadConfig(SessionManagementDoesNotOverrideExplicitRequestCacheConfig)
|
loadConfig(SessionManagementDoesNotOverrideExplicitRequestCacheConfig)
|
||||||
then:
|
then:
|
||||||
findFilter(ExceptionTranslationFilter).requestCache == SessionManagementDoesNotOverrideExplicitRequestCacheConfig.REQUEST_CACHE
|
findFilter(ExceptionTranslationFilter).requestCache == SessionManagementDoesNotOverrideExplicitRequestCacheConfig.REQUEST_CACHE
|
||||||
}
|
}
|
||||||
|
|
||||||
@EnableWebSecurity
|
@EnableWebSecurity
|
||||||
static class SessionManagementDoesNotOverrideExplicitRequestCacheConfig extends WebSecurityConfigurerAdapter {
|
static class SessionManagementDoesNotOverrideExplicitRequestCacheConfig extends WebSecurityConfigurerAdapter {
|
||||||
static RequestCache REQUEST_CACHE
|
static RequestCache REQUEST_CACHE
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void configure(HttpSecurity http) throws Exception {
|
protected void configure(HttpSecurity http) throws Exception {
|
||||||
http
|
http
|
||||||
.requestCache()
|
.requestCache()
|
||||||
.requestCache(REQUEST_CACHE)
|
.requestCache(REQUEST_CACHE)
|
||||||
.and()
|
.and()
|
||||||
.sessionManagement()
|
.sessionManagement()
|
||||||
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
|
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
def "sessionManagement does not override explict SecurityContextRepository"() {
|
def "sessionManagement does not override explict SecurityContextRepository"() {
|
||||||
setup:
|
setup:
|
||||||
SessionManagementDoesNotOverrideExplicitSecurityContextRepositoryConfig.SECURITY_CONTEXT_REPO = Mock(SecurityContextRepository)
|
SessionManagementDoesNotOverrideExplicitSecurityContextRepositoryConfig.SECURITY_CONTEXT_REPO = Mock(SecurityContextRepository)
|
||||||
when:
|
when:
|
||||||
loadConfig(SessionManagementDoesNotOverrideExplicitSecurityContextRepositoryConfig)
|
loadConfig(SessionManagementDoesNotOverrideExplicitSecurityContextRepositoryConfig)
|
||||||
then:
|
then:
|
||||||
findFilter(SecurityContextPersistenceFilter).repo == SessionManagementDoesNotOverrideExplicitSecurityContextRepositoryConfig.SECURITY_CONTEXT_REPO
|
findFilter(SecurityContextPersistenceFilter).repo == SessionManagementDoesNotOverrideExplicitSecurityContextRepositoryConfig.SECURITY_CONTEXT_REPO
|
||||||
}
|
}
|
||||||
|
|
||||||
@EnableWebSecurity
|
@EnableWebSecurity
|
||||||
static class SessionManagementDoesNotOverrideExplicitSecurityContextRepositoryConfig extends WebSecurityConfigurerAdapter {
|
static class SessionManagementDoesNotOverrideExplicitSecurityContextRepositoryConfig extends WebSecurityConfigurerAdapter {
|
||||||
static SecurityContextRepository SECURITY_CONTEXT_REPO
|
static SecurityContextRepository SECURITY_CONTEXT_REPO
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void configure(HttpSecurity http) throws Exception {
|
protected void configure(HttpSecurity http) throws Exception {
|
||||||
http
|
http
|
||||||
.securityContext()
|
.securityContext()
|
||||||
.securityContextRepository(SECURITY_CONTEXT_REPO)
|
.securityContextRepository(SECURITY_CONTEXT_REPO)
|
||||||
.and()
|
.and()
|
||||||
.sessionManagement()
|
.sessionManagement()
|
||||||
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
|
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
def "invoke sessionManagement twice does not override"() {
|
def "invoke sessionManagement twice does not override"() {
|
||||||
when:
|
when:
|
||||||
loadConfig(InvokeTwiceDoesNotOverride)
|
loadConfig(InvokeTwiceDoesNotOverride)
|
||||||
then:
|
then:
|
||||||
findFilter(SecurityContextPersistenceFilter).repo.class == NullSecurityContextRepository
|
findFilter(SecurityContextPersistenceFilter).repo.class == NullSecurityContextRepository
|
||||||
}
|
}
|
||||||
|
|
||||||
@EnableWebSecurity
|
@EnableWebSecurity
|
||||||
static class InvokeTwiceDoesNotOverride extends WebSecurityConfigurerAdapter {
|
static class InvokeTwiceDoesNotOverride extends WebSecurityConfigurerAdapter {
|
||||||
@Override
|
@Override
|
||||||
protected void configure(HttpSecurity http) throws Exception {
|
protected void configure(HttpSecurity http) throws Exception {
|
||||||
http
|
http
|
||||||
.sessionManagement()
|
.sessionManagement()
|
||||||
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
|
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
|
||||||
.and()
|
.and()
|
||||||
.sessionManagement()
|
.sessionManagement()
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
def 'SEC-2137: disable session fixation and enable concurrency control'() {
|
def 'SEC-2137: disable session fixation and enable concurrency control'() {
|
||||||
setup: "context where session fixation is disabled and concurrency control is enabled"
|
setup: "context where session fixation is disabled and concurrency control is enabled"
|
||||||
loadConfig(DisableSessionFixationEnableConcurrencyControlConfig)
|
loadConfig(DisableSessionFixationEnableConcurrencyControlConfig)
|
||||||
String originalSessionId = request.session.id
|
String originalSessionId = request.session.id
|
||||||
String credentials = "user:password"
|
String credentials = "user:password"
|
||||||
request.addHeader("Authorization", "Basic " + credentials.bytes.encodeBase64())
|
request.addHeader("Authorization", "Basic " + credentials.bytes.encodeBase64())
|
||||||
when: "authenticate"
|
when: "authenticate"
|
||||||
springSecurityFilterChain.doFilter(request, response, new MockFilterChain())
|
springSecurityFilterChain.doFilter(request, response, new MockFilterChain())
|
||||||
then: "session invalidate is not called"
|
then: "session invalidate is not called"
|
||||||
request.session.id == originalSessionId
|
request.session.id == originalSessionId
|
||||||
}
|
}
|
||||||
|
|
||||||
@EnableWebSecurity
|
@EnableWebSecurity
|
||||||
static class DisableSessionFixationEnableConcurrencyControlConfig extends WebSecurityConfigurerAdapter {
|
static class DisableSessionFixationEnableConcurrencyControlConfig extends WebSecurityConfigurerAdapter {
|
||||||
@Override
|
@Override
|
||||||
public void configure(HttpSecurity http) {
|
public void configure(HttpSecurity http) {
|
||||||
http
|
http
|
||||||
.httpBasic()
|
.httpBasic()
|
||||||
.and()
|
.and()
|
||||||
.sessionManagement()
|
.sessionManagement()
|
||||||
.sessionFixation().none()
|
.sessionFixation().none()
|
||||||
.maximumSessions(1)
|
.maximumSessions(1)
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
protected void configure(AuthenticationManagerBuilder auth) {
|
protected void configure(AuthenticationManagerBuilder auth) {
|
||||||
auth
|
auth
|
||||||
.inMemoryAuthentication()
|
.inMemoryAuthentication()
|
||||||
.withUser("user").password("password").roles("USER")
|
.withUser("user").password("password").roles("USER")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
def 'session fixation and enable concurrency control'() {
|
def 'session fixation and enable concurrency control'() {
|
||||||
setup: "context where session fixation is disabled and concurrency control is enabled"
|
setup: "context where session fixation is disabled and concurrency control is enabled"
|
||||||
loadConfig(ConcurrencyControlConfig)
|
loadConfig(ConcurrencyControlConfig)
|
||||||
def authenticatedSession
|
def authenticatedSession
|
||||||
when: "authenticate successfully"
|
when: "authenticate successfully"
|
||||||
request.servletPath = "/login"
|
request.servletPath = "/login"
|
||||||
request.method = "POST"
|
request.method = "POST"
|
||||||
request.setParameter("username", "user");
|
request.setParameter("username", "user");
|
||||||
request.setParameter("password","password")
|
request.setParameter("password","password")
|
||||||
springSecurityFilterChain.doFilter(request, response, chain)
|
springSecurityFilterChain.doFilter(request, response, chain)
|
||||||
authenticatedSession = request.session
|
authenticatedSession = request.session
|
||||||
then: "authentication is sucessful"
|
then: "authentication is sucessful"
|
||||||
response.status == HttpServletResponse.SC_MOVED_TEMPORARILY
|
response.status == HttpServletResponse.SC_MOVED_TEMPORARILY
|
||||||
response.redirectedUrl == "/"
|
response.redirectedUrl == "/"
|
||||||
when: "authenticate with the same user"
|
when: "authenticate with the same user"
|
||||||
super.setup()
|
super.setup()
|
||||||
request.servletPath = "/login"
|
request.servletPath = "/login"
|
||||||
request.method = "POST"
|
request.method = "POST"
|
||||||
request.setParameter("username", "user");
|
request.setParameter("username", "user");
|
||||||
request.setParameter("password","password")
|
request.setParameter("password","password")
|
||||||
springSecurityFilterChain.doFilter(request, response, chain)
|
springSecurityFilterChain.doFilter(request, response, chain)
|
||||||
then:
|
then:
|
||||||
response.status == HttpServletResponse.SC_MOVED_TEMPORARILY
|
response.status == HttpServletResponse.SC_MOVED_TEMPORARILY
|
||||||
response.redirectedUrl == '/login?error'
|
response.redirectedUrl == '/login?error'
|
||||||
when: 'SEC-2574: When Session Expires and authentication attempted'
|
when: 'SEC-2574: When Session Expires and authentication attempted'
|
||||||
context.publishEvent(new HttpSessionDestroyedEvent(authenticatedSession))
|
context.publishEvent(new HttpSessionDestroyedEvent(authenticatedSession))
|
||||||
super.setup()
|
super.setup()
|
||||||
request.servletPath = "/login"
|
request.servletPath = "/login"
|
||||||
request.method = "POST"
|
request.method = "POST"
|
||||||
request.setParameter("username", "user");
|
request.setParameter("username", "user");
|
||||||
request.setParameter("password","password")
|
request.setParameter("password","password")
|
||||||
springSecurityFilterChain.doFilter(request, response, chain)
|
springSecurityFilterChain.doFilter(request, response, chain)
|
||||||
then: "authentication is successful"
|
then: "authentication is successful"
|
||||||
response.status == HttpServletResponse.SC_MOVED_TEMPORARILY
|
response.status == HttpServletResponse.SC_MOVED_TEMPORARILY
|
||||||
response.redirectedUrl == "/"
|
response.redirectedUrl == "/"
|
||||||
}
|
}
|
||||||
|
|
||||||
@EnableWebSecurity
|
@EnableWebSecurity
|
||||||
static class ConcurrencyControlConfig extends WebSecurityConfigurerAdapter {
|
static class ConcurrencyControlConfig extends WebSecurityConfigurerAdapter {
|
||||||
@Override
|
@Override
|
||||||
public void configure(HttpSecurity http) {
|
public void configure(HttpSecurity http) {
|
||||||
http
|
http
|
||||||
.formLogin()
|
.formLogin()
|
||||||
.and()
|
.and()
|
||||||
.sessionManagement()
|
.sessionManagement()
|
||||||
.maximumSessions(1)
|
.maximumSessions(1)
|
||||||
.maxSessionsPreventsLogin(true)
|
.maxSessionsPreventsLogin(true)
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
protected void configure(AuthenticationManagerBuilder auth) {
|
protected void configure(AuthenticationManagerBuilder auth) {
|
||||||
auth
|
auth
|
||||||
.inMemoryAuthentication()
|
.inMemoryAuthentication()
|
||||||
.withUser("user").password("password").roles("USER")
|
.withUser("user").password("password").roles("USER")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
def "sessionManagement ObjectPostProcessor"() {
|
def "sessionManagement ObjectPostProcessor"() {
|
||||||
setup:
|
setup:
|
||||||
AnyObjectPostProcessor opp = Mock()
|
AnyObjectPostProcessor opp = Mock()
|
||||||
HttpSecurity http = new HttpSecurity(opp, authenticationBldr, [:])
|
HttpSecurity http = new HttpSecurity(opp, authenticationBldr, [:])
|
||||||
when:
|
when:
|
||||||
http
|
http
|
||||||
.sessionManagement()
|
.sessionManagement()
|
||||||
.maximumSessions(1)
|
.maximumSessions(1)
|
||||||
.and()
|
.and()
|
||||||
.and()
|
.and()
|
||||||
.build()
|
.build()
|
||||||
|
|
||||||
then: "SessionManagementFilter is registered with ObjectPostProcessor"
|
then: "SessionManagementFilter is registered with ObjectPostProcessor"
|
||||||
1 * opp.postProcess(_ as SessionManagementFilter) >> {SessionManagementFilter o -> o}
|
1 * opp.postProcess(_ as SessionManagementFilter) >> {SessionManagementFilter o -> o}
|
||||||
and: "ConcurrentSessionFilter is registered with ObjectPostProcessor"
|
and: "ConcurrentSessionFilter is registered with ObjectPostProcessor"
|
||||||
1 * opp.postProcess(_ as ConcurrentSessionFilter) >> {ConcurrentSessionFilter o -> o}
|
1 * opp.postProcess(_ as ConcurrentSessionFilter) >> {ConcurrentSessionFilter o -> o}
|
||||||
and: "ConcurrentSessionControlAuthenticationStrategy is registered with ObjectPostProcessor"
|
and: "ConcurrentSessionControlAuthenticationStrategy is registered with ObjectPostProcessor"
|
||||||
1 * opp.postProcess(_ as ConcurrentSessionControlAuthenticationStrategy) >> {ConcurrentSessionControlAuthenticationStrategy o -> o}
|
1 * opp.postProcess(_ as ConcurrentSessionControlAuthenticationStrategy) >> {ConcurrentSessionControlAuthenticationStrategy o -> o}
|
||||||
and: "CompositeSessionAuthenticationStrategy is registered with ObjectPostProcessor"
|
and: "CompositeSessionAuthenticationStrategy is registered with ObjectPostProcessor"
|
||||||
1 * opp.postProcess(_ as CompositeSessionAuthenticationStrategy) >> {CompositeSessionAuthenticationStrategy o -> o}
|
1 * opp.postProcess(_ as CompositeSessionAuthenticationStrategy) >> {CompositeSessionAuthenticationStrategy o -> o}
|
||||||
and: "RegisterSessionAuthenticationStrategy is registered with ObjectPostProcessor"
|
and: "RegisterSessionAuthenticationStrategy is registered with ObjectPostProcessor"
|
||||||
1 * opp.postProcess(_ as RegisterSessionAuthenticationStrategy) >> {RegisterSessionAuthenticationStrategy o -> o}
|
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"() {
|
def "use sharedObject trustResolver"() {
|
||||||
setup:
|
setup:
|
||||||
SharedTrustResolverConfig.TR = Mock(AuthenticationTrustResolver)
|
SharedTrustResolverConfig.TR = Mock(AuthenticationTrustResolver)
|
||||||
when:
|
when:
|
||||||
loadConfig(SharedTrustResolverConfig)
|
loadConfig(SharedTrustResolverConfig)
|
||||||
then:
|
then:
|
||||||
findFilter(SecurityContextPersistenceFilter).repo.trustResolver == SharedTrustResolverConfig.TR
|
findFilter(SecurityContextPersistenceFilter).repo.trustResolver == SharedTrustResolverConfig.TR
|
||||||
findFilter(SessionManagementFilter).trustResolver == SharedTrustResolverConfig.TR
|
findFilter(SessionManagementFilter).trustResolver == SharedTrustResolverConfig.TR
|
||||||
}
|
}
|
||||||
|
|
||||||
@EnableWebSecurity
|
@EnableWebSecurity
|
||||||
static class SharedTrustResolverConfig extends WebSecurityConfigurerAdapter {
|
static class SharedTrustResolverConfig extends WebSecurityConfigurerAdapter {
|
||||||
static AuthenticationTrustResolver TR
|
static AuthenticationTrustResolver TR
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void configure(HttpSecurity http) throws Exception {
|
protected void configure(HttpSecurity http) throws Exception {
|
||||||
http
|
http
|
||||||
.setSharedObject(AuthenticationTrustResolver, TR)
|
.setSharedObject(AuthenticationTrustResolver, TR)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user