记录Tomcat过期会话的策略

时间:2016-12-21 09:33:57

标签: session tomcat

我的Web应用程序在数据库表上记录用户登录和注销,以便我们跟踪用户活动。

当用户显式登录或注销时,这很有效,因为基础身份验证代码负责这些日志记录事件。

但是,当用户将计算机空闲30分钟时,Web会话将过期,我们将有一个Login事件而没有相应的Logout事件。

我认为解决这个问题的唯一策略是在web.xml中定义的30分钟之前触发一个javascript事件,并在会话到期之前将用户踢出。但是,这有限制需要javascript,当有人使用多个标签时,它可能会有一些意想不到的结果(即用户正在使用tab2,会话在tab1中过期)。

你对这个案子有什么建议?

2 个答案:

答案 0 :(得分:1)

在会话到期时使用会话侦听器更新数据库。

这是如何实现会话的简单示例。

https://www.mkyong.com/servlet/a-simple-httpsessionlistener-example-active-sessions-counter/

答案 1 :(得分:1)

您想使用HttpSessionListener。它是Servlet规范为这种情况定义的标准接口。

请参阅下面的警告。

import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;

public class LogoutListener implements HttpSessionListener {
  @Override
  public void sessionDestroyed(HttpSessionEvent event) {
    HttpSession session = event.getSession();
    // NOTE: You need to store some kind of user identification
    //       in the session. My example just has a "username"
    //       in here.
    String username = session.getAttribute("username");

    // If the username is null, there was no logged-in user
    // to log-out (e.g. non-authenticated user).
    if(null != username) {
      // NOTE: Obviously, this needs to call your existing
      //       "logout"-recording code. Just an example.
      MyDBUtilities.registerLogout(username, System.currentTimeMillis());
    }
  }

  @Override
  public void sessionCreated(HttpSessionEvent event) {
    // Ignore
  }
}

如果您使用上述代码,您会发现未明确注销的用户将获得单个注销记录,明确注销的用户将获得两个。为什么?因为您可能正在使用“注销”操作来编写“注销”记录,然后会话监听器立即运行并进行第二次审核。

这个问题有两个明显的解决方案:

  1. 在“注销”操作中停止记录注销事件,并让事件处理程序记录所有注销
  2. 删除用户的“用户名”会话属性,并将事件处理程序忽略该事件