1. 应用场景
在企业级Web应用中, 为了提高用户体验或者遵守一些标准(比如PCI标准), 产品经理常常会提出如下需求:
session过期后, 用户点击其它需要权限才能访问的链接时, 页面应跳转到登录页面, 并提示用户因为session过期需要重新登录.
2. 细节分析与相关技术
怎么实现呢? 我用很多个关键字google了半天, 看到了很多类似的问题, 但没有找到任何解决方案. 求人不如求己, 分析下需求, 自己找个解决方案吧.
这个需求包含三个细节:
- 如果用户关闭浏览器再访问需要权限才能访问的链接时, login页面不应显示session过期的信息;
- 如果用户logout后再访问需要权限才能访问的链接时, login页面不应显示session过期的信息;
- 仅当用户处于不活动(Inactive)状态一定时间后再访问需要权限才能访问的链接时, login页面才显示session过期的信息;
HTTP请求是无连接的, Session和Cookie是记录HTTP请求上下文关系的两种方式. 两者的主要区别是:
- Cookie由客户端(Browser)维护, 也就是说session过期后, Cookie依然是存在的, 通过request是可以取到的.
- Session由服务器维护.
显然这里是不能使用session的, 因为session已经过期了. 那么就要在Cookie上做研究了.
Cookie有两种:
- Session Cookie
- Persistent Cookie
大家所说的Cookie一般是指Persistent Cooke, 它保存在硬盘上, 可以用文本编辑器打开. Session Cookie与Persistent Cookie的区别是:
- Session Cookie在内存中, 随着浏览器的关闭而消失.
Session Cookie的这个特点很有意思, 和细节1有某种对应.
注: 在J2EE中, 如果不修改Cookie的生命期, 默认的Cookie是Session Cookie.
3. 解决方案
通过以上的分析, 我们可以了解到Session Cookie的两个特点:
- 使用Session Cookie标记用户是否已经登录, 由于用户关闭Browser后Session Cookie消失, 很好地满足了细节1.
- 由于Cookie由客户端维护, Session过期后, Session Cookie依然存在, 但Session已经不在了.
基于以上两个特点, 我们可以采用如下解决方案:
- 当用户成功登录后, 向response中添加Session Cookie, 比如HAVE_LOGIN_COOKIE, 表示用户已经登录.
- 当用户退出(Logout)后, 删除response中的HAVE_LOGIN_COOKIE Cookie.
- 设置Filter, 对所有请求, 当请求中带有HAVE_LOGIN_COOKIE, 并且request.getSession(false)得到的session为空时(意味着session已经过期), response重定向到login?session_timeout=1链接, 如果session_timeout参数非空且值为1, 显示"Session已经过期, 请重新登录"信息.
4. 参考实现
LoginAction中添加代码:
LogoutAction中添加代码:
login.jsp
Filter类:
web.xml配置