6

我正在尝试实现一个登录(记住我)应用程序,但我在管理 cookie 时遇到了问题。当我在做注册(对于新成员)或登录(对于已经注册的成员)时,我在服务器上做:

Cookie returnVisitorCookie = new Cookie("repeatVisitor", "yes");
returnVisitorCookie.setMaxAge(60*60*24*365); // 1 year
response.addCookie(returnVisitorCookie);

我从浏览器得到的响应在哪里。例如:visitor.login(response)。

当我在做 SIGNOUT 时,我正在删除 cookie。但似乎我应该有更多的 cookie,我的意思是,如果我注册了 2 个成员并退出,我仍然有名称 =“repeatVisitor”且值 =“yes”的 cookie。

也许是因为我将 cookie 放在不同的响应中。

任何人都可以给我一个 idae 我做错了什么,我应该如何实施?谢谢

4

2 回答 2

2

我有时会发现学习或理解的最佳方式是看一个例子。这是我们用于工作网站的一些代码:

@WebServlet(name = "Login", urlPatterns = {"/authorization/Login"})
public class Login extends HttpServlet {

    /**
     * Processes requests for both HTTP
     * <code>GET</code> and
     * <code>POST</code> methods.
     *
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    protected void processRequest(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.setContentType("text/html;charset=UTF-8");

        PrintWriter out = response.getWriter();
        try {
            System.out.println("Reached login");
            if (!Authorization.isLoggedIn(request)) {
                String login = request.getParameter("login");
                String password = request.getParameter("password");
                boolean remember = Boolean.parseBoolean(request.getParameter("remember"));

                System.out.println("Reached login "+login+", "+password+","+remember);
                if (!Authorization.validateLogin(login, password)) {
                    Logger.getLogger(Login.class.getName()).log(Level.INFO,
                            "Failed login (invalid password) from {0} for {1}",
                            new String[]{request.getRemoteAddr(), login});
                    response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Invalid username or password!");
                    return;
                }
                //So far so good... Get the user object from the database (unique login names)
                DB_User user = DB_User.get(login);
                if (!user.getActive()) {
                    response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Your account is no longer active!");
                    return;
                }
                String sessionID = Authorization.createNewSession(user, request.getRemoteAddr(), remember);
                Cookie sessionCookie = new Cookie("my_application.session_id", sessionID);
                sessionCookie.setDomain(request.getServerName());
                sessionCookie.setPath(request.getContextPath());
                if (remember) {
                    sessionCookie.setMaxAge(ServerConfig.getLoginSessionTimeout());
                }

                response.addCookie(sessionCookie);
            }
            response.sendRedirect("/app/myAccount.jsp");
        } catch (Throwable ex) {
            Logger.getLogger(Login.class.getName()).log(Level.SEVERE, null, ex);
            ServletUtils.handleException(ex, response);
        } finally {
            out.flush();
            out.close();
        }
    }

    // +HttpSerlet default methods here. (doGet, doPost, getServletInfo)
}

注销 servlet 示例:

@WebServlet(name = "Logout", urlPatterns = {"/authorization/Logout"})
public class Logout extends HttpServlet {

    /**
     * Processes requests for both HTTP
     * <code>GET</code> and
     * <code>POST</code> methods.
     *
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    protected void processRequest(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.setContentType("text/html;charset=UTF-8");
        PrintWriter out = response.getWriter();
        try {
            String sessionID = ServletUtils.getCookieValue(request.getCookies(),"my_application.session_id");

            if (sessionID != null) {
                SQLManager sql = ServerConfig.getSql();
                sql.deleteFromTable("login_session", "session_id = " + SQLString.toSql(sessionID));

                Cookie sessionCookie = new Cookie("my_application.session_id", null);
                sessionCookie.setDomain(ServletUtils.getCookieDomain(request));
                sessionCookie.setPath("/you_app_name");
                sessionCookie.setMaxAge(0);
                response.addCookie(sessionCookie);
            }
            response.sendRedirect("/security/login.jsp");

        } catch (Throwable ex) {
            Logger.getLogger(Logout.class.getName()).log(Level.SEVERE, null, ex);
            ServletUtils.handleException(ex, response);
        } finally {
            out.close();
        }
    }
}

正如您会注意到的,我们已经制作了一些帮助类,但这个概念仍然存在。希望这可以帮助

于 2014-03-10T22:17:35.567 回答
0

您将repeatVisitor在后续请求中保留 cookie 至少一年,您已指示客户端的浏览器这样做,“让 cookie 保持活动一年”。从后续请求标头中删除 cookie 不会阻止浏览器简单地重新添加它。

要成功实施记住我,您需要

  1. 使用安全令牌,而不仅仅是“重复用户:是”的标志。使用java 的 UUID 类之类的东西生成唯一令牌以安全地唯一标识访问者,因此有人不会拦截请求并将某些内容放在标头中供您处理

  2. 主动管理您为每个用户生成的安全令牌。这意味着您将生成的令牌存储在一些持久性存储中,并针对该存储检查重复请求。您将在此存储中管理令牌到期等。因此,在您的持久存储中,您可以将令牌标记为非活动或过期

作为替代方案,更容易记住我的路线是将您的记住我设置为固定的持续时间,您现在将在HttpServletRequest对象中设置 cookie 到期日期。也就是说,您将让您的复选框显示remember me for 2 weeks,然后将您的 cookie 有效期设置为 2 周。相同 cookie 令牌的后续表示将被自动管理而没有压力。

于 2012-10-29T17:44:17.973 回答