/* * org.nrg.xnat.security.XnatSessionEventPublisher * XNAT http://www.xnat.org * Copyright (c) 2014, Washington University School of Medicine * All Rights Reserved * * Released under the Simplified BSD. * * Last modified 7/10/13 9:04 PM */ package org.nrg.xnat.security; import org.nrg.xft.security.UserI; import org.nrg.xnat.restlet.resources.SecureResource; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.context.ApplicationContext; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.security.web.session.HttpSessionCreatedEvent; import org.springframework.security.web.session.HttpSessionDestroyedEvent; import org.springframework.web.context.support.WebApplicationContextUtils; import javax.inject.Inject; import javax.servlet.ServletContext; import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener; import javax.servlet.http.HttpSession; import javax.servlet.http.HttpSessionEvent; import javax.servlet.http.HttpSessionListener; import java.sql.Timestamp; import java.util.Calendar; import java.util.Date; import java.util.TimeZone; import java.util.UUID; public class XnatSessionEventPublisher implements HttpSessionListener, ServletContextListener { /** * Handles the HttpSessionEvent by publishing a {@link HttpSessionCreatedEvent} to the application * appContext. * * @param event HttpSessionEvent passed in by the container */ public void sessionCreated(HttpSessionEvent event) { HttpSession session = event.getSession(); HttpSessionCreatedEvent e = new HttpSessionCreatedEvent(session); if (_log.isDebugEnabled()) { _log.debug("Publishing event: " + e); } session.setAttribute("XNAT_CSRF", UUID.randomUUID().toString()); getContext(session.getServletContext()).publishEvent(e); } /** * Handles the HttpSessionEvent by publishing a {@link HttpSessionDestroyedEvent} to the application * appContext. * * @param event The HttpSessionEvent pass in by the container */ public void sessionDestroyed(final HttpSessionEvent event) { final String sessionId = event.getSession().getId(); final Date today = Calendar.getInstance(TimeZone.getDefault()).getTime(); try { final UserI user = (UserI) event.getSession().getAttribute(SecureResource.USER_ATTRIBUTE); if (user != null) { final String userId = user.getID().toString(); final Timestamp stamp = new Timestamp(today.getTime()); //sessionId's aren't guaranteed to be unique forever. But, the likelihood of sessionId and userId not forming a unique combo with a null logout_date is slim. //noinspection SqlDialectInspection,SqlNoDataSourceInspection,SqlResolve _template.execute("UPDATE xdat_user_login SET logout_date='" + stamp + "' WHERE logout_date is null and session_id='" + sessionId + "' and user_xdat_user_id='" + userId + "';"); } } catch (Exception e) { //remember, anonymous gets a session, too. Those won't be in the table. Fail silently. } HttpSessionDestroyedEvent e = new HttpSessionDestroyedEvent(event.getSession()); if (_log.isDebugEnabled()) { _log.debug("Publishing event: " + e); } getContext(event.getSession().getServletContext()).publishEvent(e); } @Override public void contextDestroyed(final ServletContextEvent event) { if (_log.isDebugEnabled()) { final ServletContext context = event.getServletContext(); _log.debug("Context destroyed: {}", context.getContextPath()); } } @Override public void contextInitialized(final ServletContextEvent event) { if (_log.isDebugEnabled()) { final ServletContext context = event.getServletContext(); _log.debug("Context initialized: {}", context.getContextPath()); } } private ApplicationContext getContext(ServletContext servletContext) { return WebApplicationContextUtils.findWebApplicationContext(servletContext); // contextAttribute in xnat's case will always be "org.springframework.web.servlet.FrameworkServlet.CONTEXT.spring-mvc"); } private static final Logger _log = LoggerFactory.getLogger(XnatSessionEventPublisher.class); @Inject private JdbcTemplate _template; }