HttpServlet(4):Cookie🍪与Session💻

71 阅读4分钟

解析源码

Cookie:

public class Cookie implements Cloneable, Serializable{

}

创建一个新的Cookie,可以看出value只能能是String

public Cookie(String name, String value) {
        if (name == null || name.length() == 0) {
            throw new IllegalArgumentException(lStrings.getString("err.cookie_name_blank"));
        }
        if (!isToken(name) || name.equalsIgnoreCase("Comment") || // rfc2019
                name.equalsIgnoreCase("Discard") || // 2019++
                name.equalsIgnoreCase("Domain") || name.equalsIgnoreCase("Expires") || // (old cookies)
                name.equalsIgnoreCase("Max-Age") || // rfc2019
                name.equalsIgnoreCase("Path") || name.equalsIgnoreCase("Secure") || name.equalsIgnoreCase("Version")
                || name.startsWith("$")) {
            String errMsg = lStrings.getString("err.cookie_name_is_token");
            Object[] errArgs = new Object[1];
            errArgs[0] = name;
            errMsg = MessageFormat.format(errMsg, errArgs);
            throw new IllegalArgumentException(errMsg);
        }

        this.name = name;
        this.value = value;
    }

我们可以在里面写很多东西

private String name; // NAME= ... "$Name" style is reserved
private String value; // value of NAME

//
// Attributes encoded in the header's cookie fields.
//
/注释信息,描述 Cookie 用途<br>⚠️ Netscape v0 不支持
private String comment; 

//指定哪些域名可以访问此 Cookie<br>必须以 . 开头(如 .example.com)
private String domain; // ;Domain=VALUE ... domain that sees cookie

// 正数(如 3600)Cookie 将在指定秒数后过期(例如 3600 秒 = 1 小时)
//负数(如 -1,默认值)Cookie 是会话级的,浏览器关闭时自动删除
//零(0)立即删除该 Cookie(常用于退出登录时清除 Cookie)
private int maxAge = -1; 

//指定哪些 URL 路径可以访问该 Cookie
private String path; 

//是否只在 HTTPS 下传输 Cookie
private boolean secure; 

//Cookie 协议版本:<br>- 0:Netscape 原始规范<br>- 1:RFC 2109 规范
private int version = 0;

//是否禁止 JavaScript 访问 Cookie(防 XSS)
private boolean isHttpOnly = false;

日常开发中最需要掌握的方法

方法用途
new Cookie(name, value)创建 Cookie
setMaxAge() / getMaxAge()控制生命周期
setPath() / getPath()控制访问路径
setDomain() / getDomain()控制域名范围
setSecure() / getSecure()控制协议安全性
setHttpOnly() / isHttpOnly()控制前端脚本访问权限
setValue() / getValue()设置/读取值

Session

Session通过req的getSession()方法获得

HttpSession session = request.getSession();
public interface HttpSession {

}

Session最重要的方法:setAttribute。value能放Object,

public void setAttribute(String name, Object value);
基本方法说明使用频率
getId()获取会话的唯一标识符(Session ID)⭐⭐⭐⭐⭐
getCreationTime()获取会话创建时间(毫秒时间戳)⭐⭐⭐☆☆
getLastAccessedTime()获取最后一次访问时间(毫秒时间戳)⭐⭐⭐☆☆
isNew()判断是否是新创建的会话⭐⭐⭐☆☆
invalidate()销毁当前会话(如用户登出)⭐⭐⭐⭐☆
setAttribute(String name, Object value)绑定一个对象到会话中(类似 Map)⭐⭐⭐⭐⭐
getAttribute(String name)获取绑定的对象⭐⭐⭐⭐⭐
removeAttribute(String name)移除指定名称的对象⭐⭐⭐☆☆
getAttributeNames()获取所有绑定对象的名称⭐⭐☆☆☆
setMaxInactiveInterval(int interval)设置最大非活动时间(秒)⭐⭐⭐⭐☆

代码示范:

// 获取或创建 Session
HttpSession session = request.getSession();

// 存储用户信息
session.setAttribute("username", "admin");
session.setAttribute("role", "administrator");

// 设置会话超时时间为30分钟
session.setMaxInactiveInterval(30 * 60); // 单位:秒

// 获取用户信息
String username = (String) session.getAttribute("username");

// 检查是否是新会话
if (session.isNew()) {
    System.out.println("这是一个新的会话");
}

// 用户登出时销毁会话
session.invalidate();

Cookie与Session的区别

  1. Cookie是把用户的数据写给浏览器,浏览器保存,同一终端并且使用同一个浏览器用户配置文件,打开浏览器看到的Cookie值都相同。缺点是只能传入字符串。

  2. Session是把用户的数据写到用户单独的Session里,每个浏览器打开的Session不相同,即使同一台电脑用同一个浏览器打开两个独立的窗口(非标签页),通常也会创建两个Session。Session可以传Object

  3. 非常重要的一点是:Session的实现依赖于Cookie(在绝大多数情况下)。

  • 当服务器创建一个Session时,它必须有一种方法将Session ID(这个Session的唯一标识符)返回给浏览器,以便浏览器在下次请求时能告诉服务器“我是谁”。
  • 最常用、最方便的方法就是使用一个特殊的Cookie,通常名为JSESSIONID (Java)、PHPSESSID (PHP)等,它的值就是这个ID。
  • 所以,可以理解为:Session是一种服务器端的用户状态管理机制,而Cookie是维持这种机制的“通行证”或“钥匙”

使用Cookie与Session

Cookie 主要用于与服务器交互的、小型的标识性数据;而 Session 用于存储在服务器端的、临时的、敏感或量大的用户状态数据。

下面这个表格清晰地展示了两者的典型分工。

存储项通常存于 Cookie 🍪通常存于 Session 💻
核心用途用户身份标识、偏好记录用户会话状态、敏感数据暂存
具体例子会话ID(Session ID)、登录状态令牌(Token)、语言或主题偏好用户登录凭证(如用户名/用户ID)、购物车商品列表、多步骤表单的临时数据、敏感信息(如手机号)
安全备注不应直接存储密码等敏感信息。关键标识(如Token)需设置 HttpOnlySecure 等安全属性。数据在服务器端,相对更安全