文章

Cookie 机制详解深度解析

Cookie 是面试必问的客户端存储与鉴权载体:讲清字段(SameSite、HttpOnly、Secure、Domain、Path)、会话保持原理与安全属性。 掌握后能说清 CSRF 防护与跨域携带 Cookie 的关键点。

Cookie 机制详解深度解析

一句话概括

Cookie 不是”前端存储”,是 HTTP 无状态协议的身份补丁。HttpOnly 防 XSS 窃取、Secure 防中间人嗅探、SameSite=Lax 防 CSRF 伪造——三条防线是 AND 关系,丢了一条,整个安全模型就破了。

核心知识点

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// ===== 方式一:后端 Set-Cookie(敏感数据的唯一通道)=====
// HTTP 响应头,浏览器自动解析并存储:
// Set-Cookie: session_id=abc123; HttpOnly; Secure; SameSite=Lax; Max-Age=3600; Path=/

// ===== 方式二:前端 document.cookie(永远设不了 HttpOnly)=====
document.cookie = 'theme=dark; Max-Age=2592000; Path=/; Secure; SameSite=Lax';

// 读的时候是一整坨字符串:
console.log(document.cookie); // "theme=dark; lang=zh"

// 手动解析——注意 value 里可能含 =,用 indexOf 定位第一个 = 切分
const parseCookie = str =>
  Object.fromEntries(
    str.split('; ').map(pair => {
      const i = pair.indexOf('=');
      return [pair.slice(0, i), pair.slice(i + 1)];
    })
  );

// 删除 Cookie = 设过期时间为过去
document.cookie = 'theme=; Max-Age=0; Path=/';

核心区分: 前端 document.cookie 永远设不了 HttpOnly。sessionId、refresh token 等敏感内容必须由后端 Set-Cookie 响应头下发——这是单向通道。

2. 五大属性——每个都关系到安全面

1
2
3
4
5
6
7
8
9
10
11
12
// 完整 Cookie:Set-Cookie: key=val; Domain=site.com; Path=/app;
//             Max-Age=3600; Secure; HttpOnly; SameSite=Lax

// Domain:决定哪些子域名能拿到这个 Cookie
// 不设 → 仅当前域名(最安全)
// .example.com → api.example.com、admin.example.com 都能看到,攻击面扩大

// Max-Age vs Expires:Max-Age 是相对秒数,Expires 是绝对时间
// Max-Age 优先级更高,推荐 Max-Age(不依赖客户端时钟)

// Secure:只在 HTTPS 传输。HTTP 明文下该 Cookie 根本不发送
// HttpOnly:JS 完全不可读,浏览器只在 HTTP 请求时自动带

3. SameSite — Chrome 80 以来最被低估的防线

1
2
3
4
5
6
7
8
9
10
11
// Strict:最严,任何跨站场景都不带 Cookie
// 用户从邮件点链接跳转到你的网站 → Cookie 不发送 → 永远是"未登录"
// Set-Cookie: token=xxx; SameSite=Strict

// Lax:Chrome 80+ 默认值,安全与体验的平衡
// ✅ <a> 点击跳转、顶层 GET 导航 → 带 Cookie
// ❌ <img src="跨站"> / iframe / fetch(POST) → 不带
// Set-Cookie: token=xxx; SameSite=Lax

// None:完全放开跨站携带 → 必须搭配 Secure,否则浏览器直接丢弃
// Set-Cookie: tracker=xxx; SameSite=None; Secure

面试加分点: Chrome 80 把默认从 None 改为 Lax 后,无数第三方登录、iframe 支付、跨域 SSO 突然挂掉。不是代码有 bug,是没显式声明 SameSite=None; Secure。面试官问”Cookie 莫名其妙丢失”就考这个。

4. 三道防线——AND 关系,不是 OR

攻击类型防线原理
XSS 窃取 CookieHttpOnlydocument.cookie 读不到
中间人嗅探SecureCookie 只在 HTTPS 传输
CSRF 伪造请求SameSite=Lax跨站 POST 不带 Cookie

残酷现实: 三条只做了两条 = 白做。只设 HttpOnly 没 Secure?HTTP 公网 WiFi 上明文被抓。只设 SameSite 没 HttpOnly?XSS 注入 script 照样偷。

其实你每天都在用

  • “两周内免登录”:勾选后后端设 Max-Age=1209600,两周内每次请求自动带 sessionId,无需重复输入密码
  • 多语言站点无感切换:lang=zh-CN 存 Cookie,后端直接返回对应语言页面,URL 不用改
  • CSRF Token 双重校验:后端下发 CSRF Token 到 Cookie(不设 HttpOnly 让 JS 可读),前端读出放进 X-CSRF-Token 请求头,服务器比对两处是否一致
  • 第三方广告追踪:网站 A 里嵌入的广告 iframe 用 SameSite=None Cookie 跨站追踪你的浏览行为
  • 未登录购物车:商品 ID 加密后存 Cookie,登录前加购的东西登录后还在

常见误解(FAQ)

  • ❌ 误区:「Cookie 只有 4KB,太废了」 把 Cookie 当存储用是方向性错误。Cookie 的价值在 Transport(自动随请求传输),不是 Storage。sessionId 只要几十字节,4KB 绰绰有余。存数据请用 localStorage / IndexedDB。

  • ❌ 误区:「SameSite=Lax 可以完全替代 CSRF Token」 Lax 解决了 POST/PUT/DELETE 的跨站伪造,但 GET /api/delete?id=123 这类设计不良的接口依然能被跨站触发(<a> 链接导航带 Cookie)。CSRF Token + SameSite 是纵深防御,不是二选一。

  • ❌ 误区:「Domain=.example.com 方便,向下兼容」 Domain 越宽暴露面越大。如果只有 www.example.com 需要这个 Cookie,不设 Domain 最安全。设了 .example.com 后,你的 staging 环境、CDN 域名甚至攻击者控制的同父域子域名都能拿到。

  • ❌ 误区:「前端 document.cookie 和后端 Set-Cookie 一样」 前端只能设置无 HttpOnly 的 Cookie(能被 JS 读写的),且操作的是字符串拼接,不是结构化 API。敏感内容(sessionId、refresh token)必须走后端 Set-Cookie 单行道。

一句话总结

HttpOnly 让脚本看不见,Secure 让中间人截不到,SameSite=Lax 让跨站请求带不走——三道防线全备,Cookie 安全才不是一句空话。

本文由作者按照 CC BY 4.0 进行授权