3

我制作了一个非常简单的登录和会话结构,以便在我未来的基于 JSP 的应用程序中重用。就像这样:

web.xml(1分钟超时是为了测试我的问题):

<session-config>
 <session-timeout>1</session-timeout>
</session-config>

<filter>
 <filter-name>Access</filter-name>
 <filter-class>com.app.Access</filter-class>
</filter>

<filter-mapping>
 <filter-name>Access</filter-name>
 <url-pattern>*</url-pattern>
</filter-mapping>

<servlet>
 <servlet-name>Login</servlet-name>
 <servlet-class>com.app.Login</servlet-class>
</servlet>

<servlet-mapping>
 <servlet-name>Login</servlet-name>
 <url-pattern>/login</url-pattern>
</servlet-mapping>

Access.java过滤器:

// Check if the page's the login or if the user logged, else asks login
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
    HttpServletRequest httpRequest = (HttpServletRequest) request;
    boolean logged = httpRequest.getSession(false) != null && httpRequest.getSession().getAttribute("user") != null;
    if (httpRequest.getServletPath().equals("/login") || logged)
        chain.doFilter(request, response);
    else
        ((HttpServletResponse) response).sendRedirect(httpRequest.getContextPath() + "/login");
}

Login.java servlet(为测试缩短了身份验证):

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    if (request.getRequestedSessionId() != null && !request.isRequestedSessionIdValid())
        request.setAttribute("failure", "session timeout");
    request.getSession().setAttribute("user", null);
    request.getRequestDispatcher("login.jsp").forward(request, response);
}

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    request.getSession().setAttribute("user", new User());
    response.sendRedirect("");
}

而位于WebContent 根目录的login.jsp<form action="login" method="post">页面有一个表单,其中包含用于身份验证的适当的 innerHTML 和一个用于接收会话超时登录失败消息的${failure}字段。

这种结构非常适合我。它拦截、请求登录、检查会话和身份验证等,但有一个小缺陷:如果您在登录页面并在超时后刷新它(F5 或在 URL 处按 Enter),页面接收并在 ${failure} 中显示“会话超时”消息。

我还没有找到真正的工作方法来让它知道上一页是登录页面。尝试了大约五种不同的方法但没有成功,包括request.getHeader("Referer")标签lastWish库。

4

2 回答 2

1

一种方法是让您的可公开访问的 JSP(例如登录页面)根本不创建会话。默认情况下,请求 JSP 页面即隐式创建会话。这可以通过在 JSP 顶部添加以下行来实现:

<%@page session="false" %>

这种方式request.getRequestedSessionId()将返回null,因此将绕过超时检查。只有在您实际登录用户时才会以这种方式创建会话。我只会从 servlet 中删除以下行,因为这没有任何意义并且仍然会创建会话:

request.getSession().setAttribute("user", null);
于 2012-07-01T01:27:26.603 回答
0

我只是这样做:

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
    HttpServletRequest httpReq = (HttpServletRequest)request;
    String servletPath = httpReq.getServletPath();
    HttpSession session = httpReq.getSession();
    String redirectUrl = "/login.jsp";
    if (
            (servletPath.endsWith("login.jsp")) ||
            (servletPath.endsWith("rss.html")) ||
            (servletPath.endsWith("httperror403.html")) ||
            (servletPath.endsWith("httperror500.html")) ||
            (servletPath.endsWith("imageMark.do"))||
            (servletPath.indexOf("/api.do") != -1) ||
            (servletPath.indexOf("/help/") != -1)){
        chain.doFilter(request, response);
    }  else if (session == null) {
        httpReq.getRequestDispatcher(redirectUrl).forward(request, response);
    } else {
        SystemUser user = (SystemUser)session.getAttribute("user");
        if (user == null){
            if (session != null){
                session.invalidate();
            }
            httpReq.getRequestDispatcher(redirectUrl).forward(request, response);
        } else {
            chain.doFilter(request, response);
        }
    }
}
于 2012-07-01T01:31:37.370 回答