Cookie、Session、Token、JWT 原理 + 流程 + 区别 + 实战

HTTP 无状态 :底层原理、完整执行流程、数据结构、安全机制、优缺点、适用场景

HTTP 是无状态协议 :服务器不记忆任何用户信息,请求之间毫无关联。→ 无法实现:登录、购物车、个人中心、权限校验。

所以:**必须给 HTTP 强行 "加状态"**这就是 Cookie、Session、Token、JWT 诞生的根本原因

后续状态指的是什么意思:

在Web 身份认证 / 服务端会话这个语境下,「状态」特指:

服务端需要主动存储、维护的「用户会话信息」(比如用户 ID、登录状态、权限、会话有效期等),用来识别和关联同一个用户的多次请求。

关键区分:

  • 有状态(Stateful) :服务端必须在本地存储用户的会话数据,每次请求都要从存储中查询、校验这个状态,才能识别用户。

  • 无状态(Stateless) :服务端不需要存储 任何用户会话数据,所有身份信息都由客户端在请求中携带,服务端只需要验证信息的合法性,就能识别用户,不依赖本地存储。

一、Cookie:浏览器的 "存储小盒子"(原理 + 细节)

1. 官方定义

Cookie 是服务器通过响应头种植、浏览器自动存储、自动携带 的键值对文本数据 。它不是认证方案 ,它是存储载体。

2. 底层原理(HTTP 头工作流程)

登录成功后,服务器在响应头里加:

复制代码
Set-Cookie: userId=123; Expires=xxx; HttpOnly; Secure; SameSite

浏览器自动解析并保存到本地。

下次请求同一域名时,请求头自动带上:

复制代码
Cookie: userId=123

全程无需代码干预。

属性 作用
Expires/Max-Age 过期时间
HttpOnly 禁止 JS 读取,防 XSS 窃取
Secure 仅 HTTPS 传输
SameSite 防 CSRF 跨站攻击

4. 本质局限

  • 大小限制 4KB
  • 纯文本,可篡改
  • 不能存敏感信息(密码、身份证)
  • 浏览器专属,APP 不支持

二、Session:服务器的 "会话账本"(原理 + 流程)

1. 一句话原理

Session = 服务器内存 / 缓存中的用户数据 Cookie = 存 SessionID(钥匙)

Session 是有状态认证。

2. 完整执行流程(最经典的 Web 登录)

① 登录请求

用户输入账号密码 → 后端验证成功

② 服务器创建 Session

复制代码
生成唯一 SessionID:sess_abc123
服务器存储:
sess_abc123 → { userId: 1, username: "张三", login: true }
复制代码
Set-Cookie: JSESSIONID=sess_abc123; HttpOnly

④ 后续请求

浏览器自动携带 Cookie:

复制代码
Cookie: JSESSIONID=sess_abc123

⑤ 服务器验证

服务器根据 sess_abc123 查存储 → 拿到用户信息 → 认证通过。

3. Session 底层原理

  • Session 存储:内存、Redis、数据库
  • SessionID:随机字符串(无法猜测)
  • 依赖 Cookie:没有 Cookie,Session 几乎无法工作

4. Session 致命缺点

  1. 服务器有状态 → 无法随便扩容
  2. 分布式 / 集群必须共享 Session(Redis 方案)
  3. 跨域极难(Cookie 不支持跨域)
  4. APP 不友好(APP 没有浏览器 Cookie 机制)

三、Token:通用 "加密身份凭证"

1. 核心思想

服务器不存储任何用户状态 → 彻底无状态

Token = 服务器签发的身份字符串

2. 与 Session 最大区别

  • Session:服务器存数据 → 查库验证
  • Token:服务器不存数据 → 解密 / 验签验证

3. Token 工作流程

① 登录成功

服务器生成 Token:

复制代码
token = encrypt(用户信息 + 过期时间 + 签名)

② 返回给前端

前端自己存储:

  • localStorage
  • cookie
  • vuex/react state

③ 后续请求(手动携带)

前端在请求头里手动加:

复制代码
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...

④ 服务器验证

解密 / 验签 → 合法 → 通过

4. Token 优点

  • 无状态,服务器零存储
  • 天然支持分布式、微服务
  • 跨域友好
  • 支持 APP、小程序、Web 全端

四、JWT:Token 的标准实现(最详细原理)

1. 官方全称

JSON Web Token 它是一套标准化的 Token 格式,不是新技术。

2. JWT 核心特点

自包含 + 防篡改 + 跨语言

3. JWT 数据结构(三段式。分割)

复制代码
Header.Payload.Signature

① Header(头部)

声明加密算法,默认 HS256

复制代码
{
  "alg": "HS256",
  "typ": "JWT"
}

② Payload(负载)

存放用户数据(不加密!仅编码)

复制代码
{
  "sub": "1",
  "name": "张三",
  "exp": 1735689600
}

Payload 可以被任何人解码,绝对不能存密码!

③ Signature(签名)【核心安全】

复制代码
Signature = HMACSHA256(
  Base64(Header) + "." + Base64(Payload),
  密钥 (SecretKey)
)

作用:防止篡改只要内容被改,签名立刻失效。

4. JWT 验证原理(超级重要)

  1. 前端传 JWT
  2. 后端拆分出 Header.Payload.Signature
  3. 用同样密钥重新计算签名
  4. 对比新签名 vs 旧签名
  • 一致 → 未篡改,可信
  • 不一致 → 伪造,拒绝

5. JWT 优点

  • 无存储、无状态
  • 跨语言、跨平台
  • 微服务、前后端分离首选
  • 不依赖 Cookie

6. JWT 缺点(必须知道)

  1. 无法主动作废未过期的 JWT 永远有效,想拉黑只能加黑名单(Redis)
  2. Payload 可解码敏感信息禁止放入
  3. 体积比 SessionID 大

五、终极对比:4 者本质关系(彻底懂)

一句话总结

  • Cookie :浏览器存储工具
  • Session :服务端存储状态(依赖 Cookie)
  • Token :无状态身份凭证
  • JWT :Token 的标准格式

最清晰的层级关系

plaintext

复制代码
HTTP 无状态
   ↓
Cookie(存储)
   ↓
Session(基于 Cookie 的服务端状态)
   ↓
Token(无状态、跨平台)
   ↓
JWT(标准 Token)

核心区别表

维度 Cookie Session Token JWT
存储位置 客户端 服务端 客户端 客户端
服务端存储 无 有 无 无
传输方式 自动 自动 手动 手动
跨域 不支持 不支持 支持 支持
分布式 不支持 需共享 天然支持 天然支持
安全性 中 高 高 高
适用端 Web Web 全端 全端

六、实战选择指南(工作中怎么选?)

1. 传统 Web 项目(不分离)

Session + Cookie最简单、最安全。

2. 前后端分离 / 微服务 / 小程序 / APP

JWT行业标准方案。

3. 超高安全需求(金融、支付)

JWT + 黑名单 + 短过期 + HTTPS

Q1:Session 为什么不适合分布式?

因为状态存在服务器本地,其他服务器查不到。

Q2:JWT 为什么安全?

因为签名无法伪造,内容一改就失效。

Q3:Cookie 被禁用了怎么办?

Session 会失效,但 JWT 不受影响。

Q4:JWT 能存密码吗?

绝对不能,因为 Payload 可解码。

Q5:JWT 泄露了怎么办?

没办法,只能等过期或拉黑。

相关推荐
小羊没烦恼!3 天前
微服务化的基石——持续集成
java·大数据·word·powerpoint·.net
俊昭喜喜里3 天前
java中的继承和多态的区别
java
小羊没烦恼!3 天前
初探性能优化——2个月到4小时的性能提升
java·开发语言·windows·算法·c#
譕痕3 天前
JSONObject与JSONArray封装数据格式区别
java·json
虎头金猫3 天前
4K 视频总卡在公网带宽?用 N1 + OpenList 把网盘播放链路重新理顺
运维·服务器·网络·python·容器·beautifulsoup·pandas
胡写代码3 天前
别再前后端各写一套表单校验了
java·后端
小鱼能吃糖3 天前
缺陷修复总览 · mall电商项目:5类缺陷,1个病根,4个业务域
java·电商
此时不提桶,更待何时3 天前
01-06-A-JVM排查实战详解
java·jvm
vipxieliang3 天前
ValidX 在 DDD 领域驱动设计中的实践
java·spring boot
ba_pi3 天前
mysql 查询所有表名并授权
java