【问题标题】:How to close a vaadin session but keep http session when browser closed?如何在浏览器关闭时关闭 vaadin 会话但保持 http 会话?
【发布时间】:2013-10-17 12:13:27
【问题描述】:

我正在开发一个 vaadin 7 应用程序,该应用程序使用 jaas 进行用户身份验证和授权,并在应用程序服务器 (glassfish) 中定义了一个领域。

我有这个要求:

  • 用户可以保持登录状态一段时间,这样他就不需要每次都输入密码。
    我通过设置 http 会话的会话超时来做到这一点。

  • vaadin 会话可以锁定一些资源,并且在锁定时,没有其他会话可以使用该资源。当 vaadin 会话关闭时,所有锁定的资源都会被释放。
    我将心跳间隔设置为仅 15 秒。

我无法同时满足这两个要求。 如果我将http会话超时设置为一分钟,则资源在关闭浏览器一分钟后释放,但用户下次不认证。
如果我将 https 会话超时设置为某些天,则这次用户已通过身份验证,但 vaadin 会话在 3 次错过心跳后不会立即关闭。只有当用户下次使用相同的 http session 使用应用程序时才会关闭它。

如何同时满足这两个要求?

这里有更多关于我正在使用的技术的信息:

  • 玻璃鱼 4
  • 网络应用 3.1
  • vaadin 7.1.7
  • vaadin-cdi 1.0-SNAPSHOT

感谢您的帮助

【问题讨论】:

  • 你能澄清一下你必须释放什么样的锁定资源吗?或者您是指一般的资源?
  • 在我的例子中,资源是数据库中的一些条目。我正在使用我自己的锁定机制。但真正的关键问题是如何在浏览器关闭后关闭 vaadin 会话而不使 http 会话无效。我现在的解决方法是只释放我锁定的数据库条目,但保留 vaadin 会话。我有一个计时器,每分钟检查一次是否仍然收到心跳。

标签: java session vaadin httpsession


【解决方案1】:

您可能想看看Spring Security,尤其是Remember-Me Authentication - 我个人会使用的替代方法,而不是尝试自己实现安全的持久登录。

如果你想走DIY之路:

我认为尝试将 Vaadin 与 Http Session 分开并不是一个好主意。 Application lifecycle section of the Vaadin book 说:

当新客户端连接时,它会创建一个新的用户会话,由 VaadinSession 的实例表示。使用存储在浏览器中的 cookie 跟踪会话。 … [Vaadin 会话] 还通过 WrappedSession 提供对较低级别会话对象 HttpSession 和 PortletSession 的访问。

也许您可以将第一个要求的解决方案(“用户可以保持登录状态一段时间,这样他就不需要每次都输入密码。”)到将登录凭据与 http 会话分开?

您可以将一些带时间戳和唯一 ID 存储为 cookie(带有过期日期)和 customize the VaadinServlet 以及您自己的 SessionInitListenerSessionDestroyListener 来检查它(并设置它),或者需要登录凭据或接受来自客户端的凭据,具体取决于您在服务器上执行的检查。

【讨论】:

  • 感谢您的回答。记住用户并不是真正的认证问题。可以使用 Spring Security 或我自己的带有令牌的 cookie。这会将身份验证与 http 会话分离。但我也在使用授权(@RolesAllowed 注释),这就是我的问题中更难的部分。当然,我也可以采用另一个框架进行授权,但我并不想这样做。
  • 当用户打开您的应用程序进行自动登录时,您不能使用身份验证信息。因此不需要更改授权代码中的任何内容。还是我错过了你提出的观点?
  • 第一次登录时,我使用用户名和密码进行编程登录(HttpServletRequest.login())。只要 http 会话存在,就可以进行授权。如果我使用令牌来记住用户,我将不得不基于该令牌进行登录。我不知道该怎么做。或者我可以在我的应用程序的某个地方记住密码,但我不喜欢这个主意。所以保持http会话一段时间对我来说似乎是最好的主意,但我想关闭vaadin会话。
  • 祝你好运。如果您找到解决方案,请发布。我认为如果不对框架内部进行一些黑客攻击,很难将新创建的 Vaadin 会话附加到现有的 http 会话。但我可能错了。
【解决方案2】:

您的问题有些含糊不清,但我相信您可以使用自己的 close() 方法解决它。您可以使用自定义的 close() 方法创建自己的 Vaadin Application 类,或者使用 TPTApplication 并覆盖其 close() 方法:

http://vaadin.com/directory#addon/toolkit-productivity-tools:vaadin

确保在会话关闭时调用关闭,并在那里进行清理。这也将在会话结束时调用。

如果您不能确保这一点(即,如果用户只是关闭窗口并且您没有一些 javascript 来处理此问题),您可以使用 Vaadin 拦截关闭窗口,但它的工作量要大得多.当用户试图关闭窗口时,您会中断该过程,通过回调执行您需要执行的操作,然后让关闭发生。有关如何从 vaadin 进行中断的详细信息如下所示:

https://vaadin.com/forum/#!/thread/44621/44668
https://vaadin.com/forum/#!/thread/83207/83206

回调仅是客户端,因此您必须调用服务器(通过 javascript 获取/发布),该服务器会将会话 id 传递给您正在监听的 servlet。然后,servlet 将使用传入的会话 id 释放锁。

关键是监听窗口关闭并能够适当地响应。

【讨论】:

  • 感谢您考虑我的问题,但我认为这不是解决我问题的方法。覆盖 UI.close() (我正在使用 vaadin 7)函数已经完成,但它没有被调用,因为如果 http 会话没有超时,vaadin 会话不会关闭。在 javascript 中捕获浏览器关闭事件是可能的,但不能保证它在所有情况下都能正常工作(例如浏览器崩溃)。我想从计时器线程或另一个会话中关闭 Vaadin 会话,但保留属于已关闭的 vaadin 会话的 http 会话。
猜你喜欢
  • 1970-01-01
  • 2012-12-28
  • 2011-12-17
  • 2012-04-11
  • 2012-04-06
  • 1970-01-01
  • 2013-08-11
  • 1970-01-01
相关资源
最近更新 更多