Skip to content

Commit 34fc3e4

Browse files
committed
Publish UserLogoutEvent also when not using Redis
1 parent a7f6c20 commit 34fc3e4

2 files changed

Lines changed: 39 additions & 36 deletions

File tree

src/main/java/eu/openanalytics/containerproxy/ContainerProxyApplication.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,8 @@ private static void setDefaultProperties(SpringApplication app) {
186186

187187
// use in-memory session storage by default. Can be overwritten in application.yml
188188
properties.put("spring.session.store-type", "none");
189+
// required for proper working of the SP_USER_INITIATED_LOGOUT session attribute in the UserService
190+
properties.put("spring.session.redis.flush-mode", "IMMEDIATE");
189191

190192
// disable multi-part handling by Spring. We don't need this anywhere in the application.
191193
// When enabled this will cause problems when proxying file-uploads to the shiny apps.

src/main/java/eu/openanalytics/containerproxy/service/UserService.java

Lines changed: 37 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -20,54 +20,50 @@
2020
*/
2121
package eu.openanalytics.containerproxy.service;
2222

23-
import java.util.*;
24-
import java.util.concurrent.ExecutionException;
25-
import java.util.concurrent.TimeUnit;
26-
27-
import javax.annotation.PostConstruct;
28-
import javax.inject.Inject;
29-
import javax.servlet.http.HttpSession;
30-
31-
import com.google.common.cache.*;
23+
import eu.openanalytics.containerproxy.auth.IAuthenticationBackend;
24+
import eu.openanalytics.containerproxy.backend.strategy.IProxyLogoutStrategy;
3225
import eu.openanalytics.containerproxy.event.AuthFailedEvent;
3326
import eu.openanalytics.containerproxy.event.UserLoginEvent;
3427
import eu.openanalytics.containerproxy.event.UserLogoutEvent;
35-
import org.apache.commons.lang3.tuple.Pair;
28+
import eu.openanalytics.containerproxy.model.runtime.Proxy;
29+
import eu.openanalytics.containerproxy.model.spec.ProxySpec;
30+
import eu.openanalytics.containerproxy.util.SessionHelper;
3631
import org.apache.logging.log4j.LogManager;
3732
import org.apache.logging.log4j.Logger;
38-
import org.apache.xpath.operations.Bool;
3933
import org.springframework.context.ApplicationEventPublisher;
40-
import org.springframework.context.ApplicationListener;
4134
import org.springframework.context.annotation.Lazy;
4235
import org.springframework.context.event.EventListener;
4336
import org.springframework.core.env.Environment;
4437
import org.springframework.security.authentication.AnonymousAuthenticationToken;
45-
import org.springframework.security.authentication.event.AbstractAuthenticationEvent;
4638
import org.springframework.security.authentication.event.AbstractAuthenticationFailureEvent;
4739
import org.springframework.security.authentication.event.AuthenticationSuccessEvent;
48-
import org.springframework.security.authentication.event.InteractiveAuthenticationSuccessEvent;
4940
import org.springframework.security.core.Authentication;
5041
import org.springframework.security.core.GrantedAuthority;
5142
import org.springframework.security.core.context.SecurityContext;
5243
import org.springframework.security.core.context.SecurityContextHolder;
53-
import org.springframework.security.core.session.SessionDestroyedEvent;
5444
import org.springframework.security.core.userdetails.User;
45+
import org.springframework.security.web.session.HttpSessionDestroyedEvent;
5546
import org.springframework.session.Session;
47+
import org.springframework.session.events.SessionCreatedEvent;
5648
import org.springframework.session.events.SessionExpiredEvent;
5749
import org.springframework.stereotype.Service;
58-
59-
import eu.openanalytics.containerproxy.auth.IAuthenticationBackend;
60-
import eu.openanalytics.containerproxy.backend.strategy.IProxyLogoutStrategy;
61-
import eu.openanalytics.containerproxy.model.runtime.Proxy;
62-
import eu.openanalytics.containerproxy.model.spec.ProxySpec;
63-
import eu.openanalytics.containerproxy.util.SessionHelper;
6450
import org.springframework.web.context.request.RequestContextHolder;
51+
import org.springframework.web.context.request.ServletRequestAttributes;
52+
53+
import javax.inject.Inject;
54+
import javax.servlet.http.HttpSession;
55+
import java.util.ArrayList;
56+
import java.util.HashSet;
57+
import java.util.List;
58+
import java.util.Set;
6559

6660

6761
@Service
6862
public class UserService {
6963

70-
private Logger log = LogManager.getLogger(UserService.class);
64+
private final static String ATTRIBUTE_USER_INITIATED_LOGOUT = "SP_USER_INITIATED_LOGOUT";
65+
66+
private final Logger log = LogManager.getLogger(UserService.class);
7167

7268
@Inject
7369
private Environment environment;
@@ -199,6 +195,10 @@ public void logout(Authentication auth) {
199195
if (logoutStrategy != null) logoutStrategy.onLogout(userId);
200196
log.info(String.format("User logged out [user: %s]", userId));
201197

198+
HttpSession session = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest().getSession();
199+
session.setAttribute(ATTRIBUTE_USER_INITIATED_LOGOUT, "true"); // mark that the user initiated the logout
200+
201+
202202
String sessionId = RequestContextHolder.currentRequestAttributes().getSessionId();
203203
applicationEventPublisher.publishEvent(new UserLogoutEvent(
204204
this,
@@ -223,27 +223,28 @@ public void onAuthenticationSuccessEvent(AuthenticationSuccessEvent event) {
223223
}
224224

225225
@EventListener
226-
public void onSessionExpiredEvent(SessionExpiredEvent event) {
227-
Session session = event.getSession();
228-
String sessionId = session.getId();
229-
230-
Set<String> attributes = session.getAttributeNames();
231-
232-
for (String attributeName : attributes) {
233-
Object attributeValue = session.getAttribute(attributeName);
234-
if (attributeValue instanceof SecurityContext) {
235-
236-
Authentication authentication = ((SecurityContext) attributeValue).getAuthentication();
226+
public void onHttpSessionDestroyedEvent(HttpSessionDestroyedEvent event) {
227+
String userInitiatedLogout = (String) event.getSession().getAttribute(ATTRIBUTE_USER_INITIATED_LOGOUT);
228+
229+
if (userInitiatedLogout != null && userInitiatedLogout.equals("true")) {
230+
// user initiated the logout
231+
// event already handled by the logout() function above -> ignore it
232+
} else {
233+
// user did not initiated the logout -> session expired
234+
// not already handled by any other handler
235+
if (!event.getSecurityContexts().isEmpty()) {
236+
SecurityContext securityContext = event.getSecurityContexts().get(0);
237+
if (securityContext == null) return;
238+
239+
Authentication authentication = securityContext.getAuthentication();
237240
String userId = ((User) authentication.getPrincipal()).getUsername();
238241

239242
applicationEventPublisher.publishEvent(new UserLogoutEvent(
240243
this,
241244
userId,
242-
sessionId,
245+
event.getSession().getId(),
243246
true
244247
));
245-
246-
break;
247248
}
248249
}
249250
}

0 commit comments

Comments
 (0)