java - 有时,Vaadin 不会在 "Session timeout"消息后使 session 无效

标签 java session vaadin session-timeout

在我的 Vaadin 应用程序中,当 Vaadin 在“ session 超时”消息后没有使 session 无效时,我遇到了一个问题。收到此消息后,用户有时可以单击链接或刷新页面并继续工作,就好像他们仍在登录一样。 我使用以下参数:

closeIdleSessions=true
heartbeatInterval=60
session-timeout=15

最后一个参数(session-timeout)也在 context.xml(session-timeout=900)和 web.xml(session-config/session-timeout=15)中设置,因为我没有从 vaadin 文档中弄清楚, vaadin servlet有没有这样的参数。

有人遇到过这个问题吗?

更新 1:修复了参数片段。

更新 2:当 Session expired 消息出现时,SessionDestroyListener.sessionDestroy 不会被触发。

UPDATE 3:由于代码错误出现了之前的错误。现在 SessionDestroyListener.sessionDestroy 被调用,但我无法从给定事件访问 HttpSession

这是我的 SessionDestroyListener 代码(请注意 if 分支之一中的注释):

private static class SynchronizerSessionDestroyListener implements SessionDestroyListener {
    @Override
    public void sessionDestroy(SessionDestroyEvent event) {
        if (event.getSession() != null){
            WrappedSession wrappedSession = event.getSession().getSession();
            if (wrappedSession instanceof WrappedHttpSession){
                WrappedHttpSession wrappedHttpSession = (WrappedHttpSession) wrappedSession;
                HttpSession httpSession = wrappedHttpSession.getHttpSession();
                if (httpSession != null){
                    try {
                        httpSession.invalidate();
                        logger.debug("Session '{}' was invalidated", httpSession.getId());
                    } catch (IllegalStateException e){
                        // do nothing, already invalidated
                        logger.debug("Session '{}' was already invalidated: {}", httpSession.getId(), e.getMessage());
                    }
                } else {
                    logger.warn("Could not invalidate http session for vaadin session: http session is null"); // THIS IS THE BRANCH WHICH IS ACTUALLY GET EXECUTED ON 'SESSION EXPIRED' MESSAGE: event.getSession().getSession() is null!
                }
            } else {
                logger.warn("Could not invalidate http session for vaadin session: event session is not an http session");
            }
        } else {
            logger.warn("Could not invalidate http session for vaadin session: event session is null");
        }
    }
}

这是我附加监听器的方式:

public class X extends VaadinServlet {
    // different class members
    @Override
    protected void servletInitialized() throws ServletException {
        super.servletInitialized();
        getService().addSessionDestroyListener(new SynchronizerSessionDestroyListener());
    }
}

最佳答案

我将尝试解释 session 失效的基本原理,也许这会有所帮助(我无法从您的问题中读出太多信息):

  • 通常 session 会在指定时间后超时 session-timeout 参数。
  • 但是你有把握心跳 间隔考虑在内。如果你的心跳间隔更短 比 session 超时(通常是),心跳将使 session 保持 Activity 状态 永远。

  • 这就是参数 closeIdleSessions 相关的地方。环境 此参数为 true 浏览器不会将心跳视为 一个有效的超时请求,但是最后一个,非心跳 请求

  • 第二个但是:何时会识别超时?客户端引擎只能在心跳或用户采取某些操作时识别这一点(因为在这两种情况下都已完成对服务器的请求)。因此,实际超时不会在指定的超时时间过去后发生,而是在超时后的下一次心跳时发生。
  • 其他情况:3次心跳丢失后,服务器也关闭session。例如。如果浏览器关闭,这将导致 session 失效,因为没有发送心跳。

示例 web.xml 以更好地解释:

<context-param>
 <!-- ATTENTION: This value is set in SECONDS -->
 <param-name>heartbeatInterval</param-name>
 <param-value>180</param-value>
</context-param>

<session-config>
  <!-- ATTENTION: This value is set in MINUTES -->
  <session-timeout>4</session-timeout>
</session-config>

<servlet>
    <servlet-name>VaadinServlet</servlet-name>
    <servlet-class>com.example.VaadinServlet</servlet-class>
    <init-param>
      <param-name>closeIdleSessions</param-name>
      <param-value>true</param-value>
    </init-param>
</servlet>

使用上面的 web.xml session 将在 6 分钟后超时(没有用户交互)。

解释:
session 超时设置为 4 分钟,但在 4 分钟时没有心跳。下一次心跳将在 6 分钟。现在客户端引擎知道 session 实际超时并将显示相应的消息。

我不确定这是否与使用 Vaadin Push 时的过程相同,因为我们有一个从客户端到服务器的连续 channel 。

来源:
Book of Vaadin - 4.8.7. Session Expiration
Book of Vaadin - 4.9.6. Other Servlet Configuration Parameters, Session Timeout After User Inactivity

附加信息:
即将推出的 Vaadin 7.6 似乎提高了客户端-服务器连接的稳定性:Blog Post

关于java - 有时,Vaadin 不会在 "Session timeout"消息后使 session 无效,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32878942/

相关文章:

vaadin - TreeTable 中可编辑行和只读行的组合

java - 从 JTable 标题拖放到 JList

java.lang.NoClassDefFoundError : Could not initialize class org. apache.commons.logging.LogFactory

java - 如何确保我得到的图片是完整的? (在 java 中)

java - 如何指定资源文件夹使用 Maven 的哪个过滤器?

具有 2FA 的 Asp.Net Identity - 记住 session 后不保留浏览器 cookie

javascript - 每天为每个新用户运行一次 javascript 函数

php - 密码保护页面的最佳方法

design-patterns - Vaadin:设计模式

security - 如何使用 Apache Shiro 处理分层角色/权限?