Cookie 概述

是服务器通过 HTTP 响应头发送给浏览器、由浏览器保存在本地的小型文本数据(通常小于 4KB)。
后续浏览器向同一服务器发送请求时,会通过 HTTP 请求头自动携带匹配的 Cookie,让服务器识别这是之前来过的客户端,从而实现状态保持。
Cookie 主要用于解决 HTTP 协议 “无状态” 的问题(HTTP 协议本身不会记录请求间的关联,Cookie 就是用来 “记住” 信息的桥梁)


Cookie 的空间小,无法存储大容量数据,如果需要存储大量数据,可以使用 localStorage;


防 CSRF 令牌:服务器下发 csrfToken=abc123 的 Cookie(带 HttpOnly),前端提交表单时需从 Cookie 中读取该令牌并放在请求体中,服务器验证令牌一致性,防止跨站请求伪造。


Cookie 工作流程

Cookie 的交互完全基于 HTTP 协议,无需前端主动干预:

  • 客户端发起首次请求:例如用户第一次访问一个 url,此时请求头中没有服务器下发的 Cookie
  • 服务器收到客户端的第一次请求后,若需要记住客户端,会在 HTTP 响应头中添加 Set-Cookie 字段,将 Cookie 数据传给浏览器
    示例:Set-Cookie: userId=123; Path=/; Max-Age=3600 这个 Cookie,有效期 1 小时
  • 浏览器解析 Set-Cookie 头,按规则将 Cookie 存储到本地
  • 当客户再次访问相同的 url 时,浏览器会自动检查本地存储的 Cookie,若 Cookie 的数据与当前请求匹配,那么就会在 HTTP 请求头中添加 Cookie 字段,将数据传给服务器。

Cookie 的属性

  • Name=Value:Cookie 的核心数据,是服务器实际需要的信息
  • Expires:Cookie 的过期事件,过期后浏览器会自动删除 Cookie,若不设置,关闭浏览器就会删除
  • Max-Age:Cookie 的有效时长,优先级高于 Expires。若设置为 0 或负数,浏览器会立马删除。
  • Path:限制 Cookie 的作用路径,只有当请求路径匹配或包含该 Path 时,浏览器才会携带 Cookie。默认为 “当前请求路径”。
  • Domain:限制 Cookie 的作用域名:只有当请求的域名匹配该 Domain 时,浏览器才会携带 Cookie。默认为 “当前请求的域名”
  • Secure:安全属性,仅当请求时 HTTPS 协议时,浏览器才会携带 Cookie。
  • HttpOnly:防止脚本攻击,设置后,前端无法通过 js 访问该 Cookie,只能由浏览器自动携带,可有效防止 XSS 攻击窃取 Cookie
  • SameSite:跨域安全属性,限制 Cookie 在跨域请求中是否携带,防止 CSRF 攻击

Cookie 的分类

  1. 会话 Cookie:没有设置 Expires 或 Max-Age 属性,仅在浏览器会话期间有效,浏览器关闭后,Cookie 自动删除;临时状态保持,比如临时购物车、未登录用户的会话标识
  2. 持久 Cookie:设置了 Expires 或 Max-Age 属性,有效期有属性值决定,长期状态保持,比如登录后 7 天内无需重新登录,就是通过持久 Cookie 实现的
  3. 第三方 Cookie:Cookie 的 “Domain” 属性与当前访问的域名不一致,通常来自广告、统计工具等第三方服务

应用场景

  • 用户登录状态维持:服务器验证账号密码正确后,下发 token=xxx(带 HttpOnly/Secure)的 Cookie,后续请求携带该 Cookie,服务器验证后确认用户已登录。
  • 购物车数据存储:未登录用户的购物车数据,可通过会话 Cookie 临时存储(关闭浏览器丢失);登录用户的购物车可通过持久 Cookie 关联到账号。
  • 用户偏好设置:比如记住用户的 “主题颜色”“语言选择”,服务器下发 theme=dark 的持久 Cookie,下次访问时自动加载偏好。
  • 防 CSRF 令牌:服务器下发 csrfToken=abc123 的 Cookie(带 HttpOnly),前端提交表单时需从 Cookie 中读取该令牌并放在请求体中,服务器验证令牌一致性,防止跨站请求伪造。

使用 Cookie

前端操作:前端只能操作 未设置 HttpOnly 属性 的 Cookie,核心通过 document.cookie API 实现

  • 读取 Cookie:document.cookie
  • 设置 Cookie:document.cookie = “key=value;
  • 删除 Cookie:Cookie 没有直接的 “删除” API,需通过 设置 Max-Age=0 或 Expires=过去时间,让浏览器自动删除

后端操作(Spring Boot):

  • 设置 Cookie:通过 HttpServletResponse.addCookie() 方法设置 Cookie:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    import javax.servlet.http.Cookie;
    import javax.servlet.http.HttpServletResponse;
    import org.springframework.web.bind.annotation.PostMapping;
    import org.springframework.web.bind.annotation.RestController;

    @RestController
    public class LoginController {

    // 登录接口:下发登录态 Cookie
    @PostMapping("/login")
    public Result login(String username, String password, HttpServletResponse response) {
    // 假设验证账号密码成功
    if ("admin".equals(username) && "123456".equals(password)) {
    Cookie loginTokenCookie = new Cookie("loginToken", "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...");

    // 设置 Cookie 属性
    loginTokenCookie.setPath("/"); // 整个应用生效
    loginTokenCookie.setMaxAge(7 * 24 * 3600); // 有效期 7 天(单位:秒)
    loginTokenCookie.setHttpOnly(true); // 前端无法 JS 访问
    loginTokenCookie.setSecure(false); // 开发环境暂不启用(生产环境设为 true,仅 HTTPS)
    loginTokenCookie.setSameSite("Lax"); // 防 CSRF

    // 下发 Cookie 到前端
    response.addCookie(loginTokenCookie);

    return Result.success("登录成功");
    } else {
    return Result.fail("账号密码错误");
    }
    }
    }