2015-10-01 102 views
3

在我的Vaadin应用程序中,当“会话超时”消息之后Vaadin不会使会话无效时出现问题。得到这个消息后,用户有时可以单击链接或刷新页面并继续工作,就好像他们仍然被登录 我使用下列参数:有时,Vaadin不会在“会话超时”消息之后使会话无效

closeIdleSessions=true 
heartbeatInterval=60 
session-timeout=15 

末参数(会话超时)是因为我没有从vaadin文档中得到清楚的结果,它在context.xml(session-timeout = 900)和web.xml(session-config/session-timeout = 15)中设置,是否有这样的vaadin servlet参数。

有人问题吗?

UPDATE 1:固定参数片段。

UPDATE 2SessionDestroyListener.sessionDestroy在出现Session expired消息时未触发。

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()); 
    } 
} 
+0

你可以发布你的'网络。 xml'看起来像那些参数?或者您是否使用注释使用参数? – JDC

回答

8

我会尽量解释如何会话失效基本上起作用,也许这有助于(我无法从你的问题中读出太多信息):

  • 通常会话将在参数 session-timeout中的指定时间后超时。
  • 你有拿心跳 间隔考虑。如果您的心跳间隔比会话超时(通常是)短 ,则心跳将永久保持会话存活 。

  • 这就是参数closeIdleSessions是相关的。将此参数设置为 此参数为true浏览器将不会将心跳作为 作为超时的有效请求,但最后的非心跳 请求

  • 秒BUT:什么时候会识别超时?客户端引擎只能在心跳或者用户采取某些行动时才能识别这种情况(因为在这两种情况下都向服务器发出了请求)。因此,当指定的超时已经过去时,实际的超时将不会发生,但在超时后下一次心跳。
  • 其他情况:在3次心跳丢失后,服务器也关闭会话。例如。如果浏览器关闭,会导致会话失效,因为没有心跳被发送。

样品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 6分钟(无需用户交互)之后的会话将超时。

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

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

来源:
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

+0

好的,但解决方案呢? –

+0

正如我所说,这只是对会话机制如何工作的解释,因为我无法重现您的确切问题。心跳间隔是否设置得太低可能是可能的? – JDC

+0

对不起,我有一个不正确的引用参数,请参阅更新的版本。心跳间隔设置为1分钟。据我所知,JEE会议比Vaadin的会议晚3次。 Vaadin有没有什么方法可以监听它自己的会话过期消息,所以我可以做jeeSession.invalidate()? –