案例1:注销:一旦我们注销,如果尝试访问以前的,它必须自动重定向到login.jsp
情况2:会话过期:如果会话在用户仍然登录的情况下过期,它必须尝试在访问上一个页面时自动重定向到 sessionExpired.jsp。
如何区分?我目前在注销时使会话无效。
案例1:注销:一旦我们注销,如果尝试访问以前的,它必须自动重定向到login.jsp
情况2:会话过期:如果会话在用户仍然登录的情况下过期,它必须尝试在访问上一个页面时自动重定向到 sessionExpired.jsp。
如何区分?我目前在注销时使会话无效。
登录时,设置一个具有较长有效期(> 24 小时)的 cookie。通过将 maxage 设置为 0,在注销时删除此 cookie。
您可以检查任何未登录的用户(即无效的会话 ID)。如果 cookie 不存在,将他重定向到 login.jsp
如果 cookie 存在,则意味着他的会话已过期,因此将他重定向到 session-expired.jsp
您可以通过检查是否HttpServletRequest#getRequestedSessionId()
不返回来测试过期会话null
(这意味着客户端已发送会话 cookie,因此假定会话仍然有效)并HttpServletRequest#isRequestedSessionIdValid()
返回false
(这意味着会话已在服务器端过期)。
简而言之:
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws ServletException, IOException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
HttpSession session = request.getSession(false);
if (request.getRequestedSessionId() != null && !request.isRequestedSessionIdValid()) {
response.sendRedirect(request.getContextPath() + "/sessionexpired.jsp");
} else if (session == null || session.getAttribute("user") == null) {
response.sendRedirect(request.getContextPath() + "/login.jsp");
} else {
chain.doFilter(request, response);
}
}
无需为额外的饼干而烦恼。将其映射Filter
到url-pattern
覆盖受保护的页面(因此不包括 sessionexpired 和登录页面!)。
不要忘记禁用浏览器在受保护页面上的页面缓存,否则当您返回浏览器历史记录时,浏览器将从缓存中加载它们,而不是向服务器发送新请求。您可以通过在调用之前 在同一过滤器中执行以下操作来实现此目的。Chain#doFilter()
response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate"); // HTTP 1.1.
response.setHeader("Pragma", "no-cache"); // HTTP 1.0.
response.setDateHeader("Expires", 0); // Proxies.
如果是我,我会在注销时清除会话并在其中创建一个名为 HasLoggedOut 的布尔值,然后将其设置为 true。然后,如果此布尔值存在于会话中,您知道他们已注销,如果不存在,则会话已超时或用户根本没有登录。
由于您仍然无法区分超时和未登录,因此我通常会决定,如果他们请求经过身份验证的页面,我只会将它们发送到会话超时页面,该页面也兼作登录页面,上面写着类似
“糟糕,我们不知道您是谁,您的会话已超时或您尚未登录,请在下方登录”
然后,这可以满足两种情况