一文搞懂 Cookie、Session、Token、JWT 的恩怨情仇

695 阅读4分钟

🔐 一文搞懂 Cookie、Session、Token、JWT 的恩怨情仇

开发路上总有几个绕不开的「小问题」,今天我们就来盘一盘 Web 开发中的四大认证机制!✨ 文末有超实用的对比表格和流程图,建议收藏备用哦~ 📌


🌟认证四骑士的诞生背景

timeline 
    title Web认证发展史 
    1994 : Netscape发明Cookie 
    2000 : PHP推广Session机制 
    2012 : OAuth2.0标准发布 
    2015 : JWT成为RFC标准 
    2022 : Passkey无密码革命

核心概念对照表

机制存储位置通信方式生命周期
🍪 Cookie浏览器自动Header携带可设置过期时间
🎟️ Session服务端SessionID传递服务端控制
🔑 Token客户端手动Header添加令牌有效期决定
🛡️ JWT客户端Bearer Token包含过期时间声明

🍪 Cookie:浏览器的小饼干

运作原理

HTTP/1.1 200 OK
Set-Cookie: username=JohnDoe; Path=/; Expires=Wed, 21 Oct 2025 07:28:00 GMT

当服务器返回这个响应头时,浏览器就像收到妈妈给的小饼干🍪一样,会把信息乖乖存起来,下次请求自动带上:

sequenceDiagram
    浏览器->>服务器: 请求登录
    服务器-->>浏览器: Set-Cookie: user_id=123
    浏览器->>服务器: 自动携带 Cookie
    服务器->>浏览器: 返回个性化内容

经典场景

  • 保持登录状态(7 天免登录)
  • 记录用户偏好(主题/语言设置)
  • 购物车信息暂存 🛒

代码示例(Node.js)

// Express设置安全Cookie 
app.get('/set-cookie', (req, res) => { 
    res.cookie('vip_pass', 'vip123', { 
        httpOnly: true, // 防XSS 
        secure: true, // HTTPS only 
        sameSite: 'Lax', // 平衡安全与便利 
        path: '/member', // 路径隔离 
        maxAge: 86400000 // 24小时有效期 
    }); 
    res.send('Cookie 已发放!'); 
 });

🎟️ Session:服务器的记事本

工作流程

graph LR
    A[用户登录] --> B[创建 Session]
    B --> C[存储 SessionID 到 Cookie]
    C --> D[后续请求验证]

代码示例(Node.js)

app.use(session({
  secret: 'my_secret_key',
  resave: false,
  saveUninitialized: true,
  cookie: { secure: true }
}));

存储方式对比

类型优点缺点
内存存储⚡ 超快读取💥 服务器重启丢失
数据库存储💾 持久化🐌 相对较慢
Redis🚀 又快又稳🔧 需要额外配置

🛠️ Session 的工业化改造

分布式 Session 方案

graph TB
    A[客户端] --> B(Nginx)
    B --> C{Session服务器1}
    B --> D{Session服务器2}
    B --> E{Session服务器3}
    C --> F[Redis集群]
    D --> F
    E --> F

性能优化三剑客

  1. 懒加载技巧
// Spring Boot 示例
@SessionAttributes(value = {"user"}, types = {User.class})
  1. 会话分片存储
# Django 配置示例
SESSION_ENGINE = "django.contrib.sessions.backends.cached_db"

# 缓存+数据库 
SESSION_COOKIE_AGE = 3600 # 1小时有效期
SESSION_SAVE_EVERY_REQUEST = True # 动态延期
  1. 自动过期机制
// Node.js 设置
app.use(session({
  cookie: { maxAge: 3600000 }, // 1小时过期
  rolling: true // 每次请求刷新有效期
}));

🔑 Token:新时代的通行证

认证流程

sequenceDiagram
    客户端->>服务器: 用户名/密码
    服务器-->>客户端: 签发 Token
    客户端->>服务器: Authorization: Bearer <token>
    服务器->>客户端: 返回数据

优势亮点

  • 🌍 跨域无压力
  • 📱 移动端友好
  • 🧩 轻松拓展权限信息

实战案例(OAuth2.0)

GET /authorize?response_type=code&client_id=CLIENT_ID&redirect_uri=REDIRECT_URI

💎 Token 的工程化实践

双令牌流动站设计

sequenceDiagram
    用户->>认证中心: 提交凭证
    认证中心-->>用户: access_token(2h) + refresh_token(7d)
    用户->>资源服务器: 携带access_token
    资源服务器-->>用户: 返回数据
    用户->>认证中心: 用refresh_token换取新access_token

🛡️ JWT(JSON Web Token):自带防伪标识的电子身份证

结构解剖

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

JWT完整生成流程

# Python生成JWT示例 
import jwt 
from datetime import datetime, timedelta 

payload = { 
   'user_id': 123, 
   'exp': datetime.utcnow() + timedelta(hours=1) 
} 

secret_key = 'your-256-bit-secret' 
token = jwt.encode(payload, secret_key, algorithm='HS256') 
print(f"生成JWT: {token}")

三大组件

pie
    title JWT 结构占比
    "Header" : 15
    "Payload" : 35
    "Signature" : 50

安全指南 ⚠️

  1. 绝不存放敏感信息
  2. 定期更换签名密钥
  3. 设置合理的有效期 ⏳

📊 终极对决:四剑客大比拼

维度CookieSessionTokenJWT
跨域支持
服务端开销
移动端友好★★☆★☆☆★★★☆★★★★
防御CSRF★☆☆★★☆★★★☆★★★★
分布式支持需要改造
有效时间控制固定动态固定声明控制
数据安全性
传输效率
开发复杂度
可扩展性一般极强

🚀 技术选型指南

决策流程图

graph TD
    A[需要持久化状态?] -->|Yes| B{敏感数据?}
    B -->|Yes| C[Session]
    B -->|No| D[Cookie]
    A -->|No| E{需要跨域?}
    E -->|Yes| F[JWT]
    E -->|No| G[普通Token]

经典组合技

  • 电商网站:Cookie + Session 🛍️
  • 微服务架构:JWT 🔗
  • 第三方登录:OAuth2.0 + Token 🤝

技术栈推荐组合

场景推荐技术栈代表框架
传统Web应用Session + RedisSpring Session
前后端分离JWT + Refresh TokenAuth0
微服务架构OAuth2.0 + JWTKeycloak
高并发系统Token + 内存缓存Redis Sentinel
物联网设备预签名TokenAWS IoT Core

💡 避坑小课堂

常见误区:

  1. 把 JWT 当 Session 用 → 遇到注销需求就抓瞎 😱
  2. 在 Cookie 存敏感信息 → 分分钟被扒光 👀
  3. 无脑选择 JWT → 可能搬石头砸自己脚 🦶

性能优化:

  • 给 JWT 加「黑名单」功能
  • 用 Redis 缓存常用 Session
  • 合理设置 Cookie 过期时间 ⏰

希望这篇长文能帮你理清这些「剪不断理还乱」的认证机制!🎉 如果觉得有帮助,欢迎转发给你身边挠头的程序员小伙伴~ 🤗 下次遇到面试官提问,记得自信地甩出这篇文章链接哦!💪