【发布时间】:2011-04-17 21:19:36
【问题描述】:
我正在开发一个 Java Web 应用程序,它将在安全的 Intranet 上运行并且不需要用户登录。但是,该应用程序确实将会话状态保持在HttpSession。用户输入不会持久保存到数据库中,直到他们在对话的某个阶段明确单击保存按钮。在此之前,他们的输入将保留在 HttpSession 对象中。如果他们的会话到期,则必须将用户定向到通知他们会话到期的页面。
除了重定向问题外,一切正常。当用户允许他们的会话空闲时间超过<session-timeout> 中定义的时间时,会话将按预期到期。但是,我尝试将用户重定向到一个简单的“您的会话已过期”页面似乎适得其反。重定向工作正常,但除非用户关闭桌面上所有打开的浏览器窗口(不仅仅是那些打开到我的 web 应用程序页面的窗口),否则他们将继续被永远重定向到“会话过期”页面。
这是我的限制:
- 客户端工作站使用 Internet Explorer。这是全公司范围的,不会很快改变。
- 作为正常工作流程的一部分,用户将在其桌面上打开多个 IE 实例。告诉他们关闭所有 IE 实例是不可接受的。
- 未在此 Web 应用程序中使用任何 AJAX 组件
我已经使用 Java Servlet Filter 实现了重定向。以下是相关代码sn-ps:
@Override
public void doFilter(
ServletRequest request,
ServletResponse response,
FilterChain filterChain)
throws IOException, ServletException {
Validate.notNull(filterConfig);
Validate.isTrue(request instanceof HttpServletRequest);
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
String requestedSessionId = httpServletRequest.getRequestedSessionId();
logger.info("requestedSessionId: " + requestedSessionId);
HttpSession httpSession = httpServletRequest.getSession(false);
if (requestedSessionId == null) {
// No need to do anything here if no session exists yet
logger.debug("No session exists yet");
filterChain.doFilter(request, response);
} else {
if (httpSession == null) {
Validate.isTrue(response instanceof HttpServletResponse);
HttpServletResponse httpServletResponse =
(HttpServletResponse) response;
handleSessionExpired(
httpServletRequest,
httpServletResponse);
} else {
if (logger.isDebugEnabled()) {
logger.debug("Session OK | requested URL: " +
httpServletRequest.getRequestURL().toString());
}
filterChain.doFilter(request, response);
}
}
}
}
private void handleSessionExpired(
HttpServletRequest httpServletRequest,
HttpServletResponse httpServletResponse)
throws IOException {
logger.warn("expired session | id: " +
httpServletRequest.getRequestedSessionId());
String expirationPageURL =
httpServletRequest.getContextPath() + "/" +
"SessionExpiredNotification.html";
httpServletResponse.sendRedirect(expirationPageURL);
}
SessionExpiredNotification.html 页面是该行的结尾。如果用户想开始新的对话,他们应该关闭这个浏览器窗口并打开一个新窗口。问题是,只要用户在其桌面上打开任何其他 Internet Explorer 实例,新浏览器窗口仍希望使用与现在无效会话关联的旧会话 id 值。这并不特定于 IE,因为我已经确认 Firefox 的行为方式完全相同。
当我的Filter 中到达此代码时:
String requestedSessionId = httpServletRequest.getRequestedSessionId();
logger.info("requestedSessionId: " + requestedSessionId);
我可以看到客户端浏览器仍然保留旧的会话 ID 值并一遍又一遍地请求它。
我不确定它是否相关,但我的 Web 应用程序容器是 Tomcat 6.x。
我的问题:
服务器 Web 应用程序如何向客户端工作站发出会话 ID 不再有效的信号以使客户端将其丢弃?
【问题讨论】:
标签: java web-applications session servlets redirect