Cookie 机制详解深度解析
Cookie 是面试必问的客户端存储与鉴权载体:讲清字段(SameSite、HttpOnly、Secure、Domain、Path)、会话保持原理与安全属性。 掌握后能说清 CSRF 防护与跨域携带 Cookie 的关键点。
一句话概括
Cookie 不是”前端存储”,是 HTTP 无状态协议的身份补丁。HttpOnly 防 XSS 窃取、Secure 防中间人嗅探、SameSite=Lax 防 CSRF 伪造——三条防线是 AND 关系,丢了一条,整个安全模型就破了。
核心知识点
1. Cookie 的两种写入方式——单向通道
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 窃取 Cookie | HttpOnly | document.cookie 读不到 |
| 中间人嗅探 | Secure | Cookie 只在 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=NoneCookie 跨站追踪你的浏览行为 - 未登录购物车:商品 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 安全才不是一句空话。