程序员必看!Token、Session、Cookie、JWT、OAuth2五兄弟的关系你搞懂了吗?
作者:佚名 时间:2025-11-16 14:08
前言
作为一个程序员,每天都在和各种登录机制打交道,但你真的搞清楚 Token、Session、Cookie、JWT、OAuth2 这五兄弟的关系了吗?今天我们用一个有趣的故事来彻底理清这些概念!
故事背景:网络王国的身份验证大作战
在遥远的网络王国里,有一座繁华的数字城市。这座城市里住着无数的用户,他们每天都要进出各种应用商店、银行、图书馆等场所。但是问题来了:如何确保每个人的身份安全,防止坏人冒充呢?
于是,国王召集了五位身份验证专家,他们就是我们今天的主角:Cookie老爷爷、Session大哥、Token二哥、JWT三弟、OAuth2小妹。
第一幕:Cookie老爷爷的传统门卫法
Cookie的故事
Cookie老爷爷是最早的身份验证专家,他的方法很简单粗暴:
"小伙子,第一次来我这里?来,我给你一个小纸条,上面写着你的信息。下次来的时候带着这个纸条,我就知道你是谁了!"
sequenceDiagram
participant 用户 as 用户
participant 浏览器 as 浏览器
participant 服务器 as ️ 服务器
用户->>浏览器: 访问网站
浏览器->>服务器: 发送请求
服务器->>浏览器: 返回Cookie (Set-Cookie)
浏览器->>浏览器: 存储Cookie
Note over 浏览器: 后续请求
浏览器->>服务器: 自动携带Cookie
服务器->>浏览器: 识别用户身份
Cookie的工作原理:
Cookie老爷爷的优缺点:
第二幕:Session大哥的保险箱策略
Session的故事
Session大哥看到Cookie老爷爷的方法有安全隐患,于是想出了一个更安全的办法:
"Cookie老爷爷,你直接把用户信息写在纸条上太危险了!我有个更好的办法:我给用户一个保险箱钥匙(Session ID),真正的宝贝(用户信息)我锁在服务器的保险箱里!"
sequenceDiagram
participant 用户 as 用户
participant 浏览器 as 浏览器
participant 服务器 as ️ 服务器
participant 存储 as Session存储
用户->>浏览器: 登录请求
浏览器->>服务器: 发送用户名密码
服务器->>存储: 创建Session数据
存储->>服务器: 返回Session ID
服务器->>浏览器: 返回Session ID (通过Cookie)
Note over 浏览器: 后续请求
浏览器->>服务器: 携带Session ID
服务器->>存储: 查询Session数据
存储->>服务器: 返回用户信息
服务器->>浏览器: 返回响应
Session的工作原理:
Session大哥的优缺点:
第三幕:Token二哥的令牌革命
Token的故事
Token二哥是个现代派,他觉得前面两位老兄的方法都有局限性:
"各位,时代变了!现在是移动互联网时代,不是所有客户端都支持Cookie。我的令牌系统更灵活:给用户一个令牌,想放哪里放哪里,想怎么传就怎么传!"
sequenceDiagram
participant 客户端 as 客户端
participant 服务器 as ️ 服务器
participant 存储 as Token存储
客户端->>服务器: 登录请求 (用户名/密码)
服务器->>服务器: 验证用户信息
服务器->>存储: 生成并存储Token
服务器->>客户端: 返回Token
客户端->>客户端: 存储Token (localStorage/内存)
Note over 客户端: 后续API请求
客户端->>服务器: 请求 + Token (Header/参数)
服务器->>存储: 验证Token有效性
存储->>服务器: 返回验证结果
服务器->>客户端: 返回API响应
Token的工作原理:
Token二哥的优缺点:
第四幕:JWT三弟的自证清白术
JWT的故事
JWT三弟是Token二哥的升级版,他有一个神奇的能力:
"二哥,你的令牌还需要服务器存储和验证,太麻烦了!看我的自证清白术:我的令牌自带签名,服务器不用存储任何信息,只要验证签名就知道令牌是否有效!"
sequenceDiagram
participant 客户端 as 客户端
participant 服务器 as ️ 服务器
客户端->>服务器: 登录请求 (用户名/密码)
服务器->>服务器: 验证用户信息
服务器->>服务器: 生成JWT (Header.Payload.Signature)
服务器->>客户端: 返回JWT Token
客户端->>客户端: 存储JWT Token
Note over 客户端: 后续API请求
客户端->>服务器: 请求 + JWT Token (Authorization Header)
服务器->>服务器: 验证JWT签名和过期时间
服务器->>客户端: 返回API响应 (无需查询数据库)
JWT的结构:
Header.Payload.Signature
JWT三弟的优缺点:
第五幕:OAuth2小妹的第三方信任网
OAuth2的故事
OAuth2小妹是最聪明的,她解决了一个复杂的问题:
"各位哥哥,你们解决的都是自家的身份验证问题。但现在用户不想记住那么多账号密码,他们希望用微信、QQ、GitHub账号登录其他网站。我的第三方授权系统就是为了解决这个问题!"
sequenceDiagram
participant 用户 as 用户
participant 客户端 as ️ 第三方应用
participant 授权服务器 as 授权服务器 (微信/GitHub)
participant 资源服务器 as 资源服务器
用户->>客户端: 点击"微信登录"
客户端->>授权服务器: 重定向到授权页面
用户->>授权服务器: 输入微信账号密码
授权服务器->>用户: 显示授权确认页面
用户->>授权服务器: 确认授权
授权服务器->>客户端: 返回授权码 (code)
客户端->>授权服务器: 用授权码换取访问令牌
授权服务器->>客户端: 返回访问令牌 (access_token)
客户端->>资源服务器: 使用令牌获取用户信息
资源服务器->>客户端: 返回用户基本信息
OAuth2的四种授权模式:
- 授权码模式 (最安全,适用于有后端的应用)
- 简化模式 (适用于纯前端应用)
- 密码模式 (适用于高度信任的应用)
- 客户端模式 (适用于服务器间通信)
OAuth2小妹的优缺点:
第六幕:五兄弟的关系梳理
他们之间的关系
经过一番介绍,我们来梳理一下这五兄弟的关系:
graph TD
A[身份验证需求] --> B[Cookie - 基础存储机制]
B --> C[Session - 服务器端状态管理]
B --> D[Token - 无状态令牌]
D --> E[JWT - 自包含令牌]
C --> F[OAuth2 - 第三方授权]
D --> F
E --> F
style A fill:#f9f,stroke:#333,stroke-width:2px
style B fill:#bbf,stroke:#333,stroke-width:2px
style C fill:#bfb,stroke:#333,stroke-width:2px
style D fill:#fbf,stroke:#333,stroke-width:2px
style E fill:#ffb,stroke:#333,stroke-width:2px
style F fill:#fbb,stroke:#333,stroke-width:2px
实际应用场景对比
场景推荐方案原因传统Web应用
Session + Cookie
简单可靠,浏览器原生支持
单页应用(SPA)
JWT
无状态,适合前后端分离
移动App
JWT 或 Token
不依赖Cookie,灵活性高
微服务架构
JWT
无状态,便于服务间通信




