Skip to content

Support new event for indicates logout success #4053

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -30,6 +30,7 @@
import org.springframework.security.web.authentication.logout.LogoutFilter;
import org.springframework.security.web.authentication.logout.LogoutHandler;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
import org.springframework.security.web.authentication.logout.LogoutSuccessEventPublishingLogoutHandler;
import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler;
import org.springframework.security.web.authentication.logout.SimpleUrlLogoutSuccessHandler;
import org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter;
Expand Down Expand Up @@ -60,6 +61,7 @@
* No shared objects are used.
*
* @author Rob Winch
* @author Kazuki Shimizu
* @since 3.2
* @see RememberMeConfigurer
*/
Expand All @@ -85,7 +87,7 @@ public LogoutConfigurer() {
}

/**
* Adds a {@link LogoutHandler}. The {@link SecurityContextLogoutHandler} is added as
* Adds a {@link LogoutHandler}. {@link SecurityContextLogoutHandler} and {@link LogoutSuccessEventPublishingLogoutHandler} are added as
* the last {@link LogoutHandler} by default.
*
* @param logoutHandler the {@link LogoutHandler} to add
Expand Down Expand Up @@ -329,6 +331,7 @@ List<LogoutHandler> getLogoutHandlers() {
*/
private LogoutFilter createLogoutFilter(H http) throws Exception {
logoutHandlers.add(contextLogoutHandler);
logoutHandlers.add(postProcess(new LogoutSuccessEventPublishingLogoutHandler()));
LogoutHandler[] handlers = logoutHandlers
.toArray(new LogoutHandler[logoutHandlers.size()]);
LogoutFilter result = new LogoutFilter(getLogoutSuccessHandler(), handlers);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
import org.springframework.security.web.authentication.session.RegisterSessionAuthenticationStrategy;
import org.springframework.security.web.authentication.session.SessionAuthenticationStrategy;
import org.springframework.security.web.authentication.session.SessionFixationProtectionStrategy;
import org.springframework.security.web.authentication.logout.LogoutHandler;
import org.springframework.security.web.context.HttpSessionSecurityContextRepository;
import org.springframework.security.web.context.NullSecurityContextRepository;
import org.springframework.security.web.context.SecurityContextRepository;
Expand All @@ -54,6 +55,7 @@
import org.springframework.security.web.session.SimpleRedirectInvalidSessionStrategy;
import org.springframework.security.web.session.SimpleRedirectSessionInformationExpiredStrategy;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;

/**
* Allows configuring session management.
Expand Down Expand Up @@ -88,6 +90,7 @@
* </ul>
*
* @author Rob Winch
* @author Kazuki Shimizu
* @since 3.2
* @see SessionManagementFilter
* @see ConcurrentSessionFilter
Expand Down Expand Up @@ -471,7 +474,6 @@ public void configure(H http) throws Exception {
http.addFilter(sessionManagementFilter);
if (isConcurrentSessionControlEnabled()) {
ConcurrentSessionFilter concurrentSessionFilter = createConccurencyFilter(http);

concurrentSessionFilter = postProcess(concurrentSessionFilter);
http.addFilter(concurrentSessionFilter);
}
Expand All @@ -480,11 +482,20 @@ public void configure(H http) throws Exception {
private ConcurrentSessionFilter createConccurencyFilter(H http) {
SessionInformationExpiredStrategy expireStrategy = getExpiredSessionStrategy();
SessionRegistry sessionRegistry = getSessionRegistry(http);
ConcurrentSessionFilter concurrentSessionFilter;
if(expireStrategy == null) {
return new ConcurrentSessionFilter(sessionRegistry);
}

return new ConcurrentSessionFilter(sessionRegistry, expireStrategy);
concurrentSessionFilter = new ConcurrentSessionFilter(sessionRegistry);
} else {
concurrentSessionFilter = new ConcurrentSessionFilter(sessionRegistry, expireStrategy);
}
@SuppressWarnings("unchecked")
LogoutConfigurer<H> logoutConf = http.getConfigurer(LogoutConfigurer.class);
List<LogoutHandler> logoutHandlers = logoutConf == null ? null : logoutConf
.getLogoutHandlers();
if (!CollectionUtils.isEmpty(logoutHandlers)) {
concurrentSessionFilter.setLogoutHandlers(logoutHandlers);
}
return concurrentSessionFilter;
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -25,13 +25,15 @@
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.security.web.authentication.logout.CookieClearingLogoutHandler;
import org.springframework.security.web.authentication.logout.LogoutFilter;
import org.springframework.security.web.authentication.logout.LogoutSuccessEventPublishingLogoutHandler;
import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler;
import org.springframework.util.StringUtils;
import org.w3c.dom.Element;

/**
* @author Luke Taylor
* @author Ben Alex
* @author Kazuki Shimizu
*/
class LogoutBeanDefinitionParser implements BeanDefinitionParser {
static final String ATT_LOGOUT_SUCCESS_URL = "logout-success-url";
Expand Down Expand Up @@ -120,6 +122,8 @@ public BeanDefinition parse(Element element, ParserContext pc) {
logoutHandlers.add(cookieDeleter);
}

logoutHandlers.add(new RootBeanDefinition(LogoutSuccessEventPublishingLogoutHandler.class));

builder.addConstructorArgValue(logoutHandlers);

return builder.getBeanDefinition();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -23,12 +23,16 @@ import org.springframework.security.config.annotation.web.configuration.EnableWe
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter
import org.springframework.security.web.authentication.RememberMeServices
import org.springframework.security.web.authentication.logout.LogoutFilter
import org.springframework.security.web.authentication.logout.LogoutSuccessEventPublishingLogoutHandler
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler
import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler
import org.springframework.security.web.csrf.CsrfLogoutHandler
import org.springframework.security.web.util.matcher.RequestMatcher

/**
*
* @author Rob Winch
* @author Kazuki Shimizu
*/
class LogoutConfigurerTests extends BaseSpringSpec {

Expand Down Expand Up @@ -251,4 +255,21 @@ class LogoutConfigurerTests extends BaseSpringSpec {
@EnableWebSecurity
static class LogoutXMLHttpRequestConfig extends WebSecurityConfigurerAdapter {
}

def "LogoutConfigurer logout handler by default configuration"() {
when:
loadConfig(DefaultWebSecurityConfig)
then:
def logoutFilter = findFilter(LogoutFilter)
logoutFilter.handler.logoutHandlers.size() == 3
logoutFilter.handler.logoutHandlers[0].class == CsrfLogoutHandler
logoutFilter.handler.logoutHandlers[1].class == SecurityContextLogoutHandler
logoutFilter.handler.logoutHandlers[2].class == LogoutSuccessEventPublishingLogoutHandler
logoutFilter.handler.logoutHandlers[2].applicationEventPublisher != null

}
@EnableWebSecurity
static class DefaultWebSecurityConfig extends WebSecurityConfigurerAdapter {
}

}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -16,6 +16,7 @@
package org.springframework.security.config.annotation.web.configurers

import groovy.transform.CompileStatic
import org.springframework.security.web.authentication.logout.LogoutSuccessEventPublishingLogoutHandler

import javax.servlet.ServletException
import javax.servlet.ServletRequest
Expand Down Expand Up @@ -43,6 +44,7 @@ import org.springframework.security.web.servletapi.SecurityContextHolderAwareReq
/**
*
* @author Rob Winch
* @author Kazuki Shimizu
*/
class ServletApiConfigurerTests extends BaseSpringSpec {

Expand Down Expand Up @@ -71,7 +73,7 @@ class ServletApiConfigurerTests extends BaseSpringSpec {
and: "requestFactory != null"
filter.requestFactory != null
and: "logoutHandlers populated"
filter.logoutHandlers.collect { it.class } == [CsrfLogoutHandler, SecurityContextLogoutHandler]
filter.logoutHandlers.collect { it.class } == [CsrfLogoutHandler, SecurityContextLogoutHandler, LogoutSuccessEventPublishingLogoutHandler]
}


Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -15,11 +15,13 @@
*/
package org.springframework.security.config.annotation.web.configurers

import org.springframework.security.web.authentication.logout.LogoutSuccessEventPublishingLogoutHandler
import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler
import org.springframework.security.web.csrf.CsrfLogoutHandler

import javax.servlet.http.HttpServletResponse

import org.springframework.mock.web.MockFilterChain
import org.springframework.mock.web.MockHttpServletRequest
import org.springframework.mock.web.MockHttpServletResponse
import org.springframework.security.authentication.AuthenticationTrustResolver
import org.springframework.security.config.annotation.AnyObjectPostProcessor
import org.springframework.security.config.annotation.BaseSpringSpec
Expand All @@ -44,6 +46,7 @@ import org.springframework.security.web.session.SessionManagementFilter
/**
*
* @author Rob Winch
* @author Kazuki Shimizu
*/
class SessionManagementConfigurerTests extends BaseSpringSpec {

Expand Down Expand Up @@ -250,4 +253,26 @@ class SessionManagementConfigurerTests extends BaseSpringSpec {
.setSharedObject(AuthenticationTrustResolver, TR)
}
}

def "logout handler by default configuration"() {
when:
loadConfig(ConcurrencyWebSecurityConfig)
then:
def concurrentSessionFilter = findFilter(ConcurrentSessionFilter)
concurrentSessionFilter.handlers.logoutHandlers.size() == 3
concurrentSessionFilter.handlers.logoutHandlers[0].class == CsrfLogoutHandler
concurrentSessionFilter.handlers.logoutHandlers[1].class == SecurityContextLogoutHandler
concurrentSessionFilter.handlers.logoutHandlers[2].class == LogoutSuccessEventPublishingLogoutHandler
concurrentSessionFilter.handlers.logoutHandlers[2].applicationEventPublisher != null
}

@EnableWebSecurity
static class ConcurrencyWebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
super.configure(http)
http.sessionManagement().maximumSessions(1)
}
}

}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2015 the original author or authors.
* Copyright 2002-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -15,6 +15,8 @@
*/
package org.springframework.security.config.http

import org.springframework.security.web.authentication.logout.LogoutSuccessEventPublishingLogoutHandler

import static org.springframework.security.config.ConfigTestUtils.AUTH_PROVIDER_XML

import javax.sql.DataSource
Expand Down Expand Up @@ -42,6 +44,7 @@ import org.springframework.security.web.authentication.rememberme.TokenBasedReme
* @author Luke Taylor
* @author Rob Winch
* @author Oliver Becker
* @author Kazuki Shimizu
*/
class RememberMeConfigTests extends AbstractHttpConfigTests {

Expand Down Expand Up @@ -110,8 +113,11 @@ class RememberMeConfigTests extends AbstractHttpConfigTests {
rmp != null
5000 == FieldUtils.getFieldValue(rememberMeServices(), "tokenValiditySeconds")
// SEC-909
logoutHandlers.size() == 2
logoutHandlers.size() == 3
logoutHandlers.get(0) instanceof SecurityContextLogoutHandler
logoutHandlers.get(1) == rememberMeServices()
logoutHandlers.get(2) instanceof LogoutSuccessEventPublishingLogoutHandler
logoutHandlers.get(2).applicationEventPublisher != null
// SEC-1281
rmp.key == "ourkey"
}
Expand All @@ -128,9 +134,11 @@ class RememberMeConfigTests extends AbstractHttpConfigTests {

expect:
rememberMeServices
logoutHandlers.size() == 2
logoutHandlers.size() == 3
logoutHandlers.get(0) instanceof SecurityContextLogoutHandler
logoutHandlers.get(1) == rememberMeServices
logoutHandlers.get(2) instanceof LogoutSuccessEventPublishingLogoutHandler
logoutHandlers.get(2).applicationEventPublisher != null
}

def rememberMeTokenValidityIsParsedCorrectly() {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -15,15 +15,13 @@
*/
package org.springframework.security.config.http

import static org.springframework.security.config.ConfigTestUtils.AUTH_PROVIDER_XML
import org.springframework.security.web.authentication.logout.LogoutSuccessEventPublishingLogoutHandler

import java.io.IOException;
import static org.springframework.security.config.ConfigTestUtils.AUTH_PROVIDER_XML

import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest
import javax.servlet.http.HttpServletResponse

import org.springframework.mock.web.MockFilterChain
import org.springframework.mock.web.MockHttpServletRequest
Expand All @@ -43,6 +41,7 @@ import org.springframework.security.web.servletapi.SecurityContextHolderAwareReq
/**
*
* @author Rob Winch
* @author Kazuki Shimizu
*/
class SecurityContextHolderAwareRequestConfigTests extends AbstractHttpConfigTests {

Expand All @@ -57,8 +56,10 @@ class SecurityContextHolderAwareRequestConfigTests extends AbstractHttpConfigTes
expect:
securityContextAwareFilter.authenticationEntryPoint.loginFormUrl == getFilter(ExceptionTranslationFilter).authenticationEntryPoint.loginFormUrl
securityContextAwareFilter.authenticationManager == getFilter(UsernamePasswordAuthenticationFilter).authenticationManager
securityContextAwareFilter.logoutHandlers.size() == 1
securityContextAwareFilter.logoutHandlers.size() == 2
securityContextAwareFilter.logoutHandlers[0].class == SecurityContextLogoutHandler
securityContextAwareFilter.logoutHandlers[1].class == LogoutSuccessEventPublishingLogoutHandler
securityContextAwareFilter.logoutHandlers[1].applicationEventPublisher != null
}

def explicitEntryPoint() {
Expand Down Expand Up @@ -112,16 +113,20 @@ class SecurityContextHolderAwareRequestConfigTests extends AbstractHttpConfigTes
securityContextAwareFilter.authenticationEntryPoint.loginFormUrl == '/login'
securityContextAwareFilter.authenticationManager == getFilters('/first/filters').find { it instanceof UsernamePasswordAuthenticationFilter}.authenticationManager
securityContextAwareFilter.authenticationManager.parent == appContext.getBean('authManager')
securityContextAwareFilter.logoutHandlers.size() == 1
securityContextAwareFilter.logoutHandlers.size() == 2
securityContextAwareFilter.logoutHandlers[0].class == SecurityContextLogoutHandler
securityContextAwareFilter.logoutHandlers[0].invalidateHttpSession == true
securityContextAwareFilter.logoutHandlers[1].class == LogoutSuccessEventPublishingLogoutHandler
securityContextAwareFilter.logoutHandlers[1].applicationEventPublisher != null

secondSecurityContextAwareFilter.authenticationEntryPoint.loginFormUrl == '/login2'
secondSecurityContextAwareFilter.authenticationManager == getFilter(UsernamePasswordAuthenticationFilter).authenticationManager
secondSecurityContextAwareFilter.authenticationManager.parent == appContext.getBean('authManager2')
securityContextAwareFilter.logoutHandlers.size() == 1
secondSecurityContextAwareFilter.logoutHandlers.size() == 2
secondSecurityContextAwareFilter.logoutHandlers[0].class == SecurityContextLogoutHandler
secondSecurityContextAwareFilter.logoutHandlers[0].invalidateHttpSession == false
secondSecurityContextAwareFilter.logoutHandlers[1].class == LogoutSuccessEventPublishingLogoutHandler
secondSecurityContextAwareFilter.logoutHandlers[1].applicationEventPublisher != null
}

def logoutCustom() {
Expand All @@ -137,11 +142,13 @@ class SecurityContextHolderAwareRequestConfigTests extends AbstractHttpConfigTes
expect:
securityContextAwareFilter.authenticationEntryPoint.loginFormUrl == getFilter(ExceptionTranslationFilter).authenticationEntryPoint.loginFormUrl
securityContextAwareFilter.authenticationManager == getFilter(UsernamePasswordAuthenticationFilter).authenticationManager
securityContextAwareFilter.logoutHandlers.size() == 2
securityContextAwareFilter.logoutHandlers.size() == 3
securityContextAwareFilter.logoutHandlers[0].class == SecurityContextLogoutHandler
securityContextAwareFilter.logoutHandlers[0].invalidateHttpSession == false
securityContextAwareFilter.logoutHandlers[1].class == CookieClearingLogoutHandler
securityContextAwareFilter.logoutHandlers[1].cookiesToClear == ['JSESSIONID']
securityContextAwareFilter.logoutHandlers[2].class == LogoutSuccessEventPublishingLogoutHandler
securityContextAwareFilter.logoutHandlers[2].applicationEventPublisher != null
}

def 'SEC-2926: Role Prefix is set'() {
Expand Down
Loading