如何在Java Web应用程序中Session过期时redirect到Login页面?

我正在JBoss AS 5中运行一个Web应用程序。我也有一个servletfilter,拦截所有到服务器的请求。 现在,如果会话已过期,我想将用户redirect到login页面。 我需要做这个'isSessionExpired()'检查filter,并需要相应的redirect用户。 我该怎么做? 我在web.xml中设置会话时间限制,如下所示:

<session-config> <session-timeout>15</session-timeout> </session-config> 

您可以使用filter并执行以下testing:

 HttpSession session = request.getSession(false);// don't create if it doesn't exist if(session != null && !session.isNew()) { chain.doFilter(request, response); } else { response.sendRedirect("/login.jsp"); } 

上面的代码是未经testing的

但这并不是最广泛的解决scheme。 您还应该在会话中testing某个特定于域的对象或标志是否可用,然后才能假定由于会话不是新用户必须login的。

如何在Java Web应用程序中Session过期时redirect到Login页面?

这是一个错误的问题。 您应该区分“用户未login”和“会话已过期”的情况。 当用户没有login时,基本上要redirect到login页面,而不是在会话过期时。 目前接受的答案只检查HttpSession#isNew() 。 但是,当用户在会话由JSP隐式创build或者没有创build会话时,在同一会话中发送了多个请求时,这显然会失败。 例如,只需按login页面上的F5即可。

如上所述,您应该检查用户是否已login。 鉴于你问这样的问题,而标准的authentication框架,如j_security_check ,Shiro,Spring Security等已经透明地pipe理这个问题(因此不需要问这种问题),只能意味着你正在使用本地的身份validation方法。

假设您将login用户存储在某个loginservlet中的会话中,如下所示:

 @WebServlet("/login") public class LoginServlet extends HttpServlet { @EJB private UserService userService; @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.getRequestDispatcher("/WEB-INF/login.jsp").forward(request, response); } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String username = request.getParameter("username"); String password = request.getParameter("password"); User user = userService.find(username, password); if (user != null) { request.getSession().setAttribute("user", user); response.sendRedirect(request.getContextPath() + "/home"); } else { request.setAttribute("error", "Unknown login, try again"); doGet(request, response); } } } 

然后你可以在下面的loginfilter中检查:

 @WebFilter("/*") public class LoginFilter implements Filter { @Override 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); String loginURI = request.getContextPath() + "/login"; boolean loggedIn = session != null && session.getAttribute("user") != null; boolean loginRequest = request.getRequestURI().equals(loginURI); if (loggedIn || loginRequest) { chain.doFilter(request, response); } else { response.sendRedirect(loginURI); } } // ... } 

没有必要摆弄脆弱的HttpSession#isNew()检查。

你也可以用这样的filter来做到这一点:

 public class RedirectFilter implements Filter { public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletRequest req=(HttpServletRequest)request; //check if "role" attribute is null if(req.getSession().getAttribute("role")==null) { //forward request to login.jsp req.getRequestDispatcher("/login.jsp").forward(request, response); } else { chain.doFilter(request, response); } } } 

你可以在本教程中看到其余部分

检查会话是新的。

 HttpSession session = request.getSession(false); if (!session.isNew()) { // Session is valid } else { //Session has expired - redirect to login.jsp } 

在filter内部注入这个会带来这样的login页面的JavaScript。 如果您不这样做,那么在您的AJAX调用中,您将获得login页面,login页面的内容将被追加。

在你的filter或redirect内插入这个脚本作为回应:

 String scr = "<script>window.location=\""+request.getContextPath()+"/login.do\"</script>"; response.getWriter().write(scr); 

你需要实现HttpSessionListener接口,服务器会通知会话超时。

喜欢这个;

 import javax.servlet.http.HttpSessionEvent; import javax.servlet.http.HttpSessionListener; public class ApplicationSessionListener implements HttpSessionListener { public void sessionCreated(HttpSessionEvent event) { System.out.println("Session Created"); } public void sessionDestroyed(HttpSessionEvent event) { //write your logic System.out.println("Session Destroyed"); } } 

检查这个例子,以更好的理解

http://www.myjavarecipes.com/how-to-catch-session-timeouts/

在会话超时之前,我们得到一个正常的请求,之后我们得到一个Ajax请求。 我们可以通过以下方式来识别它:

 String ajaxRequestHeader = request.getHeader("X-Requested-With"); if ("XMLHttpRequest".equals(ajaxRequestHeader)) { response.sendRedirect("/login.jsp"); } 

我发现这个可行的解决scheme:

 public void logout() { ExternalContext ctx = FacesContext.getCurrentInstance().getExternalContext(); String ctxPath = ((ServletContext) ctx.getContext()).getContextPath(); try { //Use the context of JSF for invalidate the session, //without servlet ((HttpSession) ctx.getSession(false)).invalidate(); //redirect with JSF context. ctx.redirect(ctxPath + "absolute/path/index.jsp"); } catch (IOException ex) { System.out.println(ex.getMessage()); } } 

当使用login时,将其用户名放在会话中:

 `session.setAttribute("USER", username);` 

在每一页的开始,你可以这样做:

 <% String username = (String)session.getAttribute("USER"); if(username==null) // if session is expired, forward it to login page %> <jsp:forward page="Login.jsp" /> <% { } %>