Skip to content

Commit b92ada4

Browse files
committed
Support new event for indicates logout success
Fixes gh-3307
1 parent ede521d commit b92ada4

File tree

8 files changed

+433
-18
lines changed

8 files changed

+433
-18
lines changed
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
/*
2+
* Copyright 2002-2016 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.springframework.security.authentication.event;
17+
18+
import org.springframework.security.core.Authentication;
19+
20+
/**
21+
* The application event which indicates successful logout.
22+
*
23+
* @author Kazuki Shimizu
24+
* @since 4.1.1
25+
*/
26+
public class LogoutSuccessEvent extends AbstractAuthenticationEvent {
27+
28+
private final boolean expired;
29+
30+
/**
31+
* Constructs a new logout success event for no expired.
32+
*
33+
* @param authentication the authentication object
34+
*/
35+
public LogoutSuccessEvent(Authentication authentication) {
36+
this(authentication, false);
37+
}
38+
39+
40+
/**
41+
* Constructs a new logout success event.
42+
*
43+
* @param authentication the authentication object
44+
* @param expired flag whether was logout by expired
45+
*/
46+
public LogoutSuccessEvent(Authentication authentication, boolean expired) {
47+
super(authentication);
48+
this.expired = expired;
49+
}
50+
51+
/**
52+
* Indicates whether was logout by expired.
53+
* @return If return {@code true}, logout by expired.
54+
*/
55+
public boolean isExpired(){
56+
return expired;
57+
}
58+
59+
}

web/src/main/java/org/springframework/security/web/authentication/logout/LogoutFilter.java

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
2+
* Copyright 2002-2016 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -27,6 +27,9 @@
2727
import javax.servlet.http.HttpServletRequest;
2828
import javax.servlet.http.HttpServletResponse;
2929

30+
import org.springframework.context.ApplicationEventPublisher;
31+
import org.springframework.context.ApplicationEventPublisherAware;
32+
import org.springframework.security.authentication.event.LogoutSuccessEvent;
3033
import org.springframework.security.core.Authentication;
3134
import org.springframework.security.core.context.SecurityContextHolder;
3235
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
@@ -49,13 +52,15 @@
4952
* which constructor was used.
5053
*
5154
* @author Ben Alex
55+
* @author Kazuki Shimizu
5256
*/
53-
public class LogoutFilter extends GenericFilterBean {
57+
public class LogoutFilter extends GenericFilterBean implements ApplicationEventPublisherAware {
5458

5559
// ~ Instance fields
5660
// ================================================================================================
5761

5862
private RequestMatcher logoutRequestMatcher;
63+
private ApplicationEventPublisher applicationEventPublisher;
5964

6065
private final List<LogoutHandler> handlers;
6166
private final LogoutSuccessHandler logoutSuccessHandler;
@@ -113,6 +118,10 @@ public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
113118
handler.logout(request, response, auth);
114119
}
115120

121+
if (applicationEventPublisher != null && auth != null) {
122+
applicationEventPublisher.publishEvent(new LogoutSuccessEvent(auth));
123+
}
124+
116125
logoutSuccessHandler.onLogoutSuccess(request, response, auth);
117126

118127
return;
@@ -142,4 +151,14 @@ public void setLogoutRequestMatcher(RequestMatcher logoutRequestMatcher) {
142151
public void setFilterProcessesUrl(String filterProcessesUrl) {
143152
this.logoutRequestMatcher = new AntPathRequestMatcher(filterProcessesUrl);
144153
}
154+
155+
/**
156+
* {@inheritDoc }
157+
* @since 4.1.1
158+
*/
159+
@Override
160+
public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
161+
this.applicationEventPublisher = applicationEventPublisher;
162+
}
163+
145164
}

web/src/main/java/org/springframework/security/web/servletapi/HttpServlet3RequestFactory.java

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,13 @@
3030

3131
import org.apache.commons.logging.Log;
3232
import org.apache.commons.logging.LogFactory;
33-
33+
import org.springframework.context.ApplicationEventPublisher;
3434
import org.springframework.security.authentication.AuthenticationCredentialsNotFoundException;
3535
import org.springframework.security.authentication.AuthenticationManager;
3636
import org.springframework.security.authentication.AuthenticationTrustResolver;
3737
import org.springframework.security.authentication.AuthenticationTrustResolverImpl;
3838
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
39+
import org.springframework.security.authentication.event.LogoutSuccessEvent;
3940
import org.springframework.security.concurrent.DelegatingSecurityContextRunnable;
4041
import org.springframework.security.core.Authentication;
4142
import org.springframework.security.core.AuthenticationException;
@@ -67,6 +68,7 @@
6768
* </ul>
6869
*
6970
* @author Rob Winch
71+
* @author Kazuki Shimizu
7072
*
7173
* @see SecurityContextHolderAwareRequestFilter
7274
* @see HttpServlet25RequestFactory
@@ -81,6 +83,7 @@ final class HttpServlet3RequestFactory implements HttpServletRequestFactory {
8183
private AuthenticationEntryPoint authenticationEntryPoint;
8284
private AuthenticationManager authenticationManager;
8385
private List<LogoutHandler> logoutHandlers;
86+
private ApplicationEventPublisher applicationEventPublisher;
8487

8588
HttpServlet3RequestFactory(String rolePrefix) {
8689
this.rolePrefix = rolePrefix;
@@ -159,7 +162,15 @@ public void setTrustResolver(AuthenticationTrustResolver trustResolver) {
159162
this.trustResolver = trustResolver;
160163
}
161164

162-
@Override
165+
/**
166+
* Set the {@link ApplicationEventPublisher}.
167+
* @param applicationEventPublisher event publisher to be used by this object
168+
* @since 4.1.1
169+
*/
170+
public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher){
171+
this.applicationEventPublisher = applicationEventPublisher;
172+
}
173+
163174
public HttpServletRequest create(HttpServletRequest request,
164175
HttpServletResponse response) {
165176
return new Servlet3SecurityContextHolderAwareRequestWrapper(request,
@@ -245,16 +256,18 @@ public void login(String username, String password) throws ServletException {
245256
@Override
246257
public void logout() throws ServletException {
247258
List<LogoutHandler> handlers = HttpServlet3RequestFactory.this.logoutHandlers;
259+
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
248260
if (handlers == null) {
249261
HttpServlet3RequestFactory.this.logger.debug(
250262
"logoutHandlers is null, so allowing original HttpServletRequest to handle logout");
251263
super.logout();
252-
return;
264+
} else {
265+
for (LogoutHandler logoutHandler : handlers) {
266+
logoutHandler.logout(this, response, authentication);
267+
}
253268
}
254-
Authentication authentication = SecurityContextHolder.getContext()
255-
.getAuthentication();
256-
for (LogoutHandler logoutHandler : handlers) {
257-
logoutHandler.logout(this, this.response, authentication);
269+
if (applicationEventPublisher != null && authentication != null) {
270+
applicationEventPublisher.publishEvent(new LogoutSuccessEvent(authentication));
258271
}
259272
}
260273

web/src/main/java/org/springframework/security/web/servletapi/SecurityContextHolderAwareRequestFilter.java

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
2+
* Copyright 2002-2016 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -27,6 +27,8 @@
2727
import javax.servlet.http.HttpServletRequest;
2828
import javax.servlet.http.HttpServletResponse;
2929

30+
import org.springframework.context.ApplicationEventPublisher;
31+
import org.springframework.context.ApplicationEventPublisherAware;
3032
import org.springframework.security.authentication.AuthenticationManager;
3133
import org.springframework.security.authentication.AuthenticationTrustResolver;
3234
import org.springframework.security.authentication.AuthenticationTrustResolverImpl;
@@ -71,8 +73,9 @@
7173
* @author Ben Alex
7274
* @author Luke Taylor
7375
* @author Rob Winch
76+
* @author Kazuki Shimizu
7477
*/
75-
public class SecurityContextHolderAwareRequestFilter extends GenericFilterBean {
78+
public class SecurityContextHolderAwareRequestFilter extends GenericFilterBean implements ApplicationEventPublisherAware {
7679
// ~ Instance fields
7780
// ================================================================================================
7881

@@ -88,6 +91,8 @@ public class SecurityContextHolderAwareRequestFilter extends GenericFilterBean {
8891

8992
private AuthenticationTrustResolver trustResolver = new AuthenticationTrustResolverImpl();
9093

94+
private ApplicationEventPublisher applicationEventPublisher;
95+
9196
// ~ Methods
9297
// ========================================================================================================
9398

@@ -200,6 +205,7 @@ private HttpServletRequestFactory createServlet3Factory(String rolePrefix) {
200205
factory.setAuthenticationEntryPoint(this.authenticationEntryPoint);
201206
factory.setAuthenticationManager(this.authenticationManager);
202207
factory.setLogoutHandlers(this.logoutHandlers);
208+
factory.setApplicationEventPublisher(this.applicationEventPublisher);
203209
return factory;
204210
}
205211

@@ -210,4 +216,14 @@ private HttpServletRequestFactory createServlet3Factory(String rolePrefix) {
210216
private boolean isServlet3() {
211217
return ClassUtils.hasMethod(ServletRequest.class, "startAsync");
212218
}
219+
220+
/**
221+
* {@inheritDoc}
222+
* @since 4.1.1
223+
*/
224+
@Override
225+
public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
226+
this.applicationEventPublisher = applicationEventPublisher;
227+
}
228+
213229
}

web/src/main/java/org/springframework/security/web/session/ConcurrentSessionFilter.java

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
2+
* Copyright 2002-2016 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -26,6 +26,9 @@
2626
import javax.servlet.http.HttpServletResponse;
2727
import javax.servlet.http.HttpSession;
2828

29+
import org.springframework.context.ApplicationEventPublisher;
30+
import org.springframework.context.ApplicationEventPublisherAware;
31+
import org.springframework.security.authentication.event.LogoutSuccessEvent;
2932
import org.springframework.security.core.Authentication;
3033
import org.springframework.security.core.context.SecurityContextHolder;
3134
import org.springframework.security.core.session.SessionInformation;
@@ -59,15 +62,17 @@
5962
* </p>
6063
*
6164
* @author Ben Alex
65+
* @author Kazuki Shimizu
6266
*/
63-
public class ConcurrentSessionFilter extends GenericFilterBean {
67+
public class ConcurrentSessionFilter extends GenericFilterBean implements ApplicationEventPublisherAware {
6468
// ~ Instance fields
6569
// ================================================================================================
6670

6771
private SessionRegistry sessionRegistry;
6872
private String expiredUrl;
6973
private LogoutHandler[] handlers = new LogoutHandler[] { new SecurityContextLogoutHandler() };
7074
private RedirectStrategy redirectStrategy = new DefaultRedirectStrategy();
75+
private ApplicationEventPublisher applicationEventPublisher;
7176

7277
// ~ Methods
7378
// ========================================================================================================
@@ -145,6 +150,10 @@ private void doLogout(HttpServletRequest request, HttpServletResponse response)
145150
for (LogoutHandler handler : handlers) {
146151
handler.logout(request, response, auth);
147152
}
153+
154+
if (applicationEventPublisher != null && auth != null) {
155+
applicationEventPublisher.publishEvent(new LogoutSuccessEvent(auth, true));
156+
}
148157
}
149158

150159
public void setLogoutHandlers(LogoutHandler[] handlers) {
@@ -155,4 +164,14 @@ public void setLogoutHandlers(LogoutHandler[] handlers) {
155164
public void setRedirectStrategy(RedirectStrategy redirectStrategy) {
156165
this.redirectStrategy = redirectStrategy;
157166
}
167+
168+
/**
169+
* {@inheritDoc}
170+
* @since 4.1.1
171+
*/
172+
@Override
173+
public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
174+
this.applicationEventPublisher = applicationEventPublisher;
175+
}
176+
158177
}

0 commit comments

Comments
 (0)