我正在开发一个Java Web应用程序,它将在安全的Intranet上运行,并且不需要用户登录。然而,该应用程序确实保持HttpSession
中的对话状态。用户输入不会持久保存到数据库,除非他们在对话的某个阶段显式单击保存按钮。在此之前,他们的输入被保留在HttpSession
对象中。如果他们的会话过期,则用户必须定向到通知他们会话过期的页面。如何让客户端浏览器停止请求过期的会话ID?
这工作正常,除了重定向的问题。当用户允许他们的会话闲置时间超过<session-timeout>
中定义的时间时,会话将按预期期满。但是,我尝试将用户重定向到一个简单的“您的会话已过期”页面似乎已经倒闭了。重定向工作正常,但除非用户关闭桌面上的所有打开的浏览器窗口(不仅仅是打开我的Web应用程序页面),否则他们将继续永久重定向到“会话过期”页面。
这里是我的约束:
- 客户端工作站使用Internet Explorer。这是全公司范围,不会很快改变。
- 用户将在其桌面上打开多个IE实例作为其正常工作流程的一部分。告诉他们关闭IE的所有实例是不可接受的。
- 没有使用此网络应用
我实现重定向与Java Servlet中Filter
任何AJAX组件。以下是相关的代码片段:
@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不再有效,使得客户端将放弃呢?
我需要用户看到一个简单的页面,告诉他们旧的会话已过期,他们未保存的输入以前已丢失他们开始新的会议。如果我调用getSession(true),那么它不会继续进行新的对话而没有任何迹象表明最后一个被丢弃了? – 2010-09-27 17:30:27
不,这会为用户创建一个新的会话,servlet容器将通过向用户发送更新的JSESSIONID cookie来响应该会话。您重定向到SessionExpiredNotification.html仍然有效。 – 2010-09-27 18:44:22
@matt_b好的,我会做一些改变,并尝试你的方式 – 2010-09-28 13:18:19