如何在Java Web应用程序中过期会话时重定向到“登录”页面?

时间:2009-06-22 12:10:50

标签: java servlets login servlet-filters

我正在JBoss AS 5中运行一个Web应用程序。我还有一个servlet过滤器,它拦截了对服务器的所有请求。现在,如果会话已过期,我想将用户重定向到登录页面。我需要执行此操作'isSessionExpired()'检查过滤器并需要相应地重定向用户。我该怎么做?我在web.xml中设置会话时间限制,如下所示:

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

9 个答案:

答案 0 :(得分:54)

您可以使用Filter并执行以下测试:

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");
}

以上代码未经测试

然而,这不是最广泛的解决方案。您还应测试会话中是否有某些特定于域的对象或标志,然后再假设因为会话不是新用户必须已登录。偏执

答案 1 :(得分:17)

  

如何在Java Web应用程序中过期会话时重定向到“登录”页面?

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

如上所述,您应该检查用户是否已登录。鉴于你在问{Q}},Shiro,Spring Security等标准身份验证框架时已经提出这样的问题这一事实已经透明地管理了这个问题(因此没有必要对它们提出这样的问题) ,这只能意味着您正在使用自行开发的身份验证方法。

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

j_security_check

然后您可以在登录filter中检查,如下所示:

@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);
        }
    }

}

无需纠结于@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); } } // ... } 次脆弱的检查。

答案 2 :(得分:7)

你也可以使用这样的过滤器:

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);
    }
}
}

答案 3 :(得分:5)

检查会话是否是新的。

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

答案 4 :(得分:5)

在过滤器内部注入这个JavaScript,这将带来这样的登录页面。 如果你不这样做,那么在你的AJAX调用中,你将获得登录页面,并且将附加登录页面的内容。

在过滤器或重定向内插入此脚本作为响应:

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

答案 5 :(得分:2)

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

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

答案 6 :(得分:2)

您需要实现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/

答案 7 :(得分:0)

我找到了这个可行的解决方案:

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());
    }
}

答案 8 :(得分:-2)

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

`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" />
<% { } %>