一、Cookie 是什么?浏览器的「身份小饼干」
(一)Cookie 的本质:浏览器存储的「迷你档案袋」
Cookie 是浏览器存储的小文本数据,以 键值对 形式存在,比如 user=admin。它的核心使命是让无状态的 HTTP 协议「记住」用户 —— 就像你去咖啡店办了张会员卡,每次消费刷一下,店员就知道你爱喝冰美式不加糖。
浏览器会自动把 Cookie 塞进请求头,比你记得带钥匙还自觉 🔑。当你访问网站时,服务器通过解析 Cookie 识别你的身份、记录登录状态,甚至保存购物车信息。
(二)HTTP 协议的「健忘症」与 Cookie 的救赎
- HTTP 无状态之痛:早期的 HTTP 协议像金鱼一样只有 7 秒记忆(其实是完全无状态),每次请求都是独立的。比如你登录后点击「加入购物车」,服务器根本不知道这俩操作是同一个用户干的。
- Cookie 如何补坑:HTTP/1.0 引入请求头后,服务器可以通过响应头
Set-Cookie下发 Cookie(比如Set-Cookie: uid=123),浏览器收到后自动存储。后续请求会携带该 Cookie,服务器就能「认出」你啦。
二、Cookie 的核心特性:小身材大作用
(一)天生自带「三围限制」
- 容量小:单个 Cookie 通常不超过 4KB(相当于 4 张自拍的文字版),浏览器对每个域名的 Cookie 数量也有限制(一般 50 个左右)。
- 域名绑定:Cookie 有强烈的「地域意识」,只能被颁发它的域名及其子域名访问,跨域?没门!(除非设置
Domain属性,但安全性会打折扣)。 - 过期机制:可以设置
Expires或Max-Age让 Cookie 到期自动失效,比如Expires=Thu, 18 Dec 2030 12:00:00 GMT,不然它会在浏览器关闭时消失(会话级 Cookie)。
(二)关键属性解析:每一个参数都有小心思
// 服务器通过 Set-Cookie 响应头设置 Cookie,常见属性如下:
Set-Cookie: user=admin;
Expires=Thu, 18 Dec 2030 12:00:00 GMT; // 过期时间
Path=/; // 生效路径,当前域名下所有路径都能访问
Domain=example.com; // 生效域名(默认当前域名)
Secure; // 仅 HTTPS 传输时携带
HttpOnly; // 禁止 JavaScript 访问,防 XSS 攻击
SameSite=Strict; // 防止跨站请求伪造(CSRF),可选 Strict/Lax/None
三、前后端如何玩转 Cookie?从登录到状态保持全流程
(一)前端:发起请求 & 处理响应
1. 登录表单提交(以 fetch 为例)
// 阻止表单默认提交
loginForm.addEventListener('submit', async (e) => {
e.preventDefault();
const username = usernameInput.value.trim();
const password = passwordInput.value.trim();
try {
// 发送 POST 请求到登录接口
const response = await fetch('/login', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ username, password }),
});
const data = await response.json();
if (data.success) {
console.log('登录成功,Cookie 已自动存储');
// 后续请求会自动携带服务器设置的 Cookie
}
} catch (error) {
console.error('登录失败:', error);
}
});
2. 检查登录状态:依赖 Cookie 自动携带
// 页面加载时检查是否登录
document.addEventListener('DOMContentLoaded', async () => {
const response = await fetch('/check-login'); // 简单的 GET 请求
const data = await response.json();
if (data.loggedIn) {
showWelcomeSection(data.username); // 显示登录后的界面
} else {
showLoginForm(); // 显示登录表单
}
});
(二)后端:设置 Cookie & 验证身份(Node.js 示例)
const http = require('http');
const fs = require('fs');
const server = http.createServer((req, res) => {
// 登录接口:验证通过后设置 Cookie
if (req.method === 'POST' && req.url === '/login') {
let body = '';
req.on('data', (chunk) => body += chunk);
req.on('end', () => {
const { username, password } = JSON.parse(body);
// 模拟用户名密码校验(实际需加密处理)
if (username === 'admin' && password === '123456') {
// 设置 Cookie:用户名为 admin,有效期 7 天
res.setHeader('Set-Cookie', 'user=admin; Max-Age=604800; Path=/; HttpOnly');
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({ success: true, msg: '登录成功' }));
} else {
res.writeHead(401, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({ success: false, msg: '用户名或密码错误' }));
}
});
}
// 检查登录状态接口:解析请求头中的 Cookie
if (req.method === 'GET' && req.url === '/check-login') {
const cookies = req.headers.cookie || '';
const isLoggedIn = cookies.includes('user=admin'); // 实际需解析完整 Cookie
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({ loggedIn: isLoggedIn, username: isLoggedIn ? 'admin' : '' }));
}
});
server.listen(8080, () => {
console.log('服务器启动,监听 8080 端口');
});
四、Cookie vs 其他前端存储:选对工具才是硬道理
(一)存储方案对比表
| 特性 | Cookie | localStorage | sessionStorage | IndexDB |
|---|---|---|---|---|
| 容量 | 4KB 左右 | 5-10MB | 5-10MB | 无限(受磁盘限制) |
| 过期机制 | 可设置过期时间或会话级 | 永久存储 | 浏览器关闭后清除 | 需手动清除 |
| 网络传输 | 自动携带到请求头 | 不参与传输 | 不参与传输 | 不参与传输 |
| 跨窗口共享 | 同域名下共享 | 同域名下共享 | 仅当前标签页 | 同域名下共享 |
| 典型场景 | 身份认证、会话保持 | 持久化配置、缓存 | 临时会话数据 | 大量数据存储 |
(二)什么时候选 Cookie?
- 必须自动携带:比如登录状态需要每个请求都带上身份信息,Cookie 是唯一自动参与网络传输的存储方案。
- 跨域限制严格:虽然 Cookie 跨域麻烦,但通过
Domain和SameSite属性可以精准控制访问范围,安全性更高。 - 兼容性要求高:IE6 就支持 Cookie,适合需要兼容古老浏览器的场景(虽然现在很少见了)。
五、避坑指南:Cookie 常见问题与最佳实践
(一)安全隐患与防护
- XSS 攻击:恶意脚本可能通过
document.cookie窃取 Cookie,解决方案:设置HttpOnly属性(禁止 JS 访问)+Secure(仅 HTTPS 传输)。 - CSRF 攻击:攻击者伪造请求携带你的 Cookie,解决方案:设置
SameSite=Strict(严格禁止跨站请求)或Lax(宽松模式,仅限 GET 方法)。 - 敏感信息存储:永远不要直接存储密码等敏感数据!Cookie 应存储 Token,通过 Token 换取服务器端的用户信息。
(二)性能优化技巧
- 减少 Cookie 大小:合并必要的键值对,避免存储冗余信息(比如把
user_id存为数字而非长字符串)。 - 合理设置 Path:如果 Cookie 只在
/api路径下生效,就设置Path=/api,避免向无关路径发送 Cookie。 - 区分会话级与持久化 Cookie:临时登录用会话级 Cookie(浏览器关闭即失效),长期登录用持久化 Cookie 并设置合理过期时间。
六、总结:Cookie 虽小,却是身份认证的核心枢纽
从 HTTP 协议的「健忘症」到浏览器的「自动记忆」,Cookie 用小小的文本数据解决了大问题。它是前后端身份认证的桥梁,是状态保持的基石,更是理解浏览器存储体系的起点。
下次当你登录网站时,不妨打开浏览器开发者工具(F12),在 Application 面板看看那些默默工作的「小饼干」—— 它们正用自己的方式,让每个请求都带着你的专属印记 。