3

除了关闭浏览器(我没有删除 cookie)之外,我的 servlet 正在按预期工作,会话丢失。如何无限期地保存会话,直到我将其无效或删除我的 cookie?

@WebServlet(name="ServletOne", urlPatterns={"/", "/ServletOne"})
public class ServletOne extends HttpServlet {
    private static final long serialVersionUID = 1L;

    public void doGet(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
        HttpSession session = request.getSession(true);
        String newValue = request.getParameter("newValue");

        if (session.isNew()) {
            session = request.getSession(true);
            session.setAttribute("myAttribute", "value");
        }

        if (newValue != null)
            session.setAttribute("myAttribute", newValue);

        RequestDispatcher rd = request.getRequestDispatcher("test.jsp");
        rd.forward(request, response);
    }

    public void doPost(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
        doGet(request, response);
    }
}

我的 JSP:

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
    val == <c:out value="${myAttribute}"></c:out><br>
    <form action="ServletOne" method="POST">
        <input type="text" name="newValue" />
        <input type="submit" />
    </form>
</body>
</html>

如果我关闭浏览器并重新打开它,myAttribute总是设置为默认的“值”。

4

1 回答 1

6

看起来您完全误解了会话 cookie 的工作原理。

只要浏览器实例存在并且您在目标 URL 上触发 HTTP 请求,会话 cookie 就会存在,该目标 URLpath在默认服务器端会话到期时间之前的时间内被 cookie 覆盖 - 默认为 30 分钟。

一旦关闭浏览器实例(阅读:浏览器会话),所有会话 cookie 都将消失。这是完全指定的、预期的和自然的行为。几十年来,Web 浏览器一直以这种方式工作。请注意,HttpSession与 cookie 关联的实例仍然存在于服务器中。如果您HttpSessionListener基于此相关答案SessionTimeout: web.xml vs session.maxInactiveInterval()实现一个,那么您会注意到sessionDestroyed()在浏览器关闭时不会立即调用该方法,而是在 30 多分钟后才调用。

如果您重新打开浏览器实例并在其服务器端到期之前的时间内执行会话劫持攻击,那么您将能够保留关联的HttpSession实例。

也可以看看:


现在,回到让 cookie 存活时间比浏览器会话更长的具体功能要求,这实际上非常简单:创建自己的 cookie,它不是会话 cookie。即不要将cookie 设置maxAge-1(默认值),而是将其设置为以秒为单位的指定时间。

Cookie cookie = new Cookie("someCommonName", "someUniqueValue");
cookie.setMaxAge(ageInSeconds); // Use e.g. 2952000 for 30 days.
response.addCookie(cookie);

someUniqueValue又可以是类似的东西java.util.UUID。您可以将该值用作某些数据存储系统(SQL DB?)的键,您还可以在其中保存该myattribute值。在每个后续请求中,只需通过 . 检查 cookie 是否存在request.getCookies()。这样您就可以将其与客户端相关联。如有必要,将其缓存在 HTTP 会话中,这样您就不需要检查每个 HTTP 请求。

也可以看看:

于 2013-09-03T15:04:04.233 回答