【前端存储系列】Cookie 全解析:从「小饼干」到身份认证的核心担当

485 阅读6分钟

一、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 其他前端存储:选对工具才是硬道理

(一)存储方案对比表

特性CookielocalStoragesessionStorageIndexDB
容量4KB 左右5-10MB5-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 面板看看那些默默工作的「小饼干」—— 它们正用自己的方式,让每个请求都带着你的专属印记 。