Question

In cases where the user has closed the browser and walked away, I want to log when the session times out. For example as a system induced log out as opposed to user request (I already have working and tested code to log a user requested logout).

Since the user isn't actively submitting requests (especially if it is just a matter of the now unused session timing out on the server) I don't think a filter is possible. Can this be done with a phase listener? If so can you provide some insight or a skeleton, or at least point me in the right direction on how this might be done.

My understanding is that the session on the server is still active until it times out or some other mechanism invalidates it. I am assuming therefore that a phase listener will also be able to tell if as part of your login method, you kill any existing session prior to the user logging in again with a fresh view, other machine, etc.

I am OK with research, but would like to at least start while pointed in the right direction. :)

On a second note: Is it possible to differentiate between a session time out and a view expired?


Thought I'd post the solution I ended up with based on the suggestions:

public class ElsSoulardSessionListener implements HttpSessionListener {

    @EJB
    private SessionLogger sessionLogger = new SessionLogger();
    private SessionLogDTO sessionData = new SessionLogDTO();
    private ElsDateTimeFunctions ts = new ElsDateTimeFunctions();
    private static final Logger logger = Logger.getLogger(ElsSoulardSessionListener.class.getSimpleName());

    @Override
    public void sessionCreated(HttpSessionEvent se) {
        // Nothing to do yet
    }

    @Override
    public void sessionDestroyed(HttpSessionEvent se) {
        logger.log(Level.FINE, "SESSION DESTROYED LISTENER");

        HttpSession session = se.getSession();
        finalizeUserSessionLog(session);
    }

    /**
     * Utility method to finalize user's session log entry. Returns 
     * early if the session log isn't found or more than one is returned.
     * @param session 
     */
    private void finalizeUserSessionLog(HttpSession session) {

        String sessionId = session.getId();
        LogoutReasonType logoutReason = (LogoutReasonType) session.getAttribute("logoutreason");

        if (logoutReason == null) {
            logoutReason = LogoutReasonType.SESSION_TIMEOUT;
        }

        try {
            sessionData = sessionLogger.findBySessionId(sessionId);
        } catch (NonexistentEntityException | UnexpectedResultSetSizeException ex) {
            logger.log(Level.WARNING, " sessionDestroyed ", ex);
            return;
        }

        Calendar now = ts.getUtcDateTimeAsCalendar();
        sessionData.setLogoutTimestamp(now);
        sessionData.setLogoutReason(logoutReason);
        sessionLogger.update(sessionData);

    }
}
Was it helpful?

Solution

If this helps you...

In our application we have extended HttpSessionListener and used sessionDestroyed method to log the event of session timeout.

and registered the same in web.xml as

<listener>
    <listener-class>
        com.ourpackage.OurHttpSessionListener
    </listener-class>
</listener>

OTHER TIPS

I believe which you only catch events of the servlet container through ServletFilters. PhaseListener only exist inside JSF "sessions", after servlet requests. Check the JSF life cycle to make sure. After, you can create another request for invalidate the "session" in JSF

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top