JSON Web Token

4 阅读8分钟

JWT

JWT(JSON Web Token) 是基于 RFC 7519 标准的轻量级、自包含的开放数据传输标准,主要用于网络应用中的身份认证与安全信息交换。其核心优势是无状态、自包含、可跨域、易扩展,特别适合前后端分离、微服务与分布式架构。

一、JWT 结构

JWT 是一段由 . 分隔的 Base64URL 编码字符串,格式固定为三部分:

Header.Payload.Signature

示例:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
1. Header(头部)
  • 作用:描述令牌元数据(类型、签名算法)

  • 格式:JSON → Base64URL 编码

  • 典型字段

    • alg:签名算法(如 HS256RS256ES256
    • typ:固定为 JWT

示例:

{
  "alg": "HS256",
  "typ": "JWT" 
}
2. Payload(载荷 / 声明)
  • 作用:存放实际业务数据(用户 ID、权限、过期时间等)
  • 格式:JSON → Base64URL 编码
  • ⚠️ 注意仅编码、未加密严禁存放密码、手机号等敏感明文

三类声明(Claims)

  1. 标准注册声明(推荐)

    • iss:签发者(如服务域名)
    • sub:主题(通常是用户 ID)
    • aud:受众(接收方)
    • exp:过期时间(Unix 时间戳,必须大于签发时间)
    • nbf:在此时间前不可用
    • iat:签发时间
    • jti:JWT ID(唯一标识,防重放)
  2. 公共声明

    • 自定义公开字段(如 name, role, scope
  3. 私有声明

    • 通信双方约定的私有字段

示例:

{
    "sub": "1234567890",
    "name": "John Doe",
    "role": "admin",
    "iat": 1516239022,
    "exp": 1516242622 
}
3. Signature(签名)
  • 作用:验证 Header+Payload 未被篡改确保发送方真实可信
  • 生成公式
Signature = HMAC-SHA256( Base64URL(Header) + "." + Base64URL(Payload), 密钥/私钥 )
  • 常见算法

    • HS256(对称):单密钥签名 + 验证,简单高效
    • RS256(非对称):私钥签名、公钥验证,更安全
    • ES256(椭圆曲线):短密钥、高安全性

二、JWT 认证流程(典型场景)

  1. 用户登录:客户端提交用户名 / 密码
  2. 服务端验证:验证账号密码 → 生成 JWT
  3. 返回令牌:服务端将 JWT 发给客户端
  4. 客户端存储:存在 localStorage/sessionStorage/cookie
  5. 后续请求
    • 放在 HTTP Header:Authorization: Bearer <token>
    • 或 POST 参数、URL 参数
  6. 服务端验证
    • 拆分 Header.Payload.Signature
    • 用相同算法 / 密钥重新计算签名
    • 对比签名是否一致、检查 exp 是否过期
  7. 通过则处理请求

三、核心特点

  • 自包含:令牌自带所有必要信息,无需查会话库
  • 无状态:服务端不存会话状态,水平扩展极方便
  • 跨域 / 跨服务:可在多域名、微服务间传递
  • 紧凑高效:体积小,可在 URL/Header/POST 中传输
  • 语言无关:支持几乎所有主流语言

四、优缺点

✅ 优点
  • 分布式 / 微服务友好(无状态、易共享)
  • 减少数据库 / Redis 查询(自包含)
  • 跨域、跨平台、跨技术栈通用
  • 易于实现单点登录(SSO)
❌ 缺点
  • 令牌不可主动作废(除非引入黑名单 / Redis)
  • Payload 仅编码不加密,敏感信息不能明文放
  • 体积比 SessionID 大,占用少量更多带宽
  • 需严格控制过期时间(exp

五、常见应用场景

  • 前后端分离项目(Vue/React/ 小程序)身份认证
  • API 接口授权(开放平台、第三方调用)
  • 微服务内部鉴权、网关认证
  • 单点登录(SSO)
  • 一次性短时效授权(密码重置、邮箱验证)

六、安全最佳实践

  1. 必须使用 HTTPS(防止中间人截获 Token)
  2. 短过期时间(access_token:15~60 分钟)
  3. 双令牌机制
    • Access Token:短时效,用于业务请求
    • Refresh Token:较长时效,仅用于刷新 Access Token
  4. 敏感信息不放 Payload(如密码、身份证)
  5. 密钥高强度、定期轮换
  6. 关键操作二次验证(支付、改密)
  7. 必要时实现令牌黑名单(登出 / 改密后加入黑名单)

七、JWT vs Session-Cookie(对比)

表格

特性JWTSession-Cookie
状态无状态(服务端不存)有状态(服务端存 Session)
分布式天然支持需共享 Session(Redis)
跨域良好受 Cookie 跨域限制
存储位置客户端(localStorage/cookie)服务端(内存 / Redis)
主动失效难(需黑名单)易(服务端直接删除)
带宽较大(Token 较长)小(仅 SessionID)

总结

JWT 是现代无状态认证的主流方案,以 Header.Payload.Signature 结构实现安全、自包含、可跨域的身份与授权传递。核心是签名防篡改、自包含、无状态。使用时务必:HTTPS + 短过期 + 双令牌 + 不存敏感明文

对比JWT和传统的基于Session的认证方式的优缺点

下面用最清晰、最直白、面试常考的方式,对比 JWT 认证传统 Session-Cookie 认证 的优缺点。

一、核心原理一句话总结

  • Session-Cookie
    客户端只存一个 SessionID,服务端在内存 / Redis 里存用户完整会话信息。
    有状态认证
  • JWT
    令牌本身包含用户信息,服务端不存会话,只通过签名验证合法性。
    无状态认证

二、详细优缺点对比

1. 服务端状态

Session

  • 优点:服务端完全控制会话,可随时销毁、踢人、修改权限
  • 缺点:有状态,分布式环境必须共享 Session(Redis)

JWT

  • 优点:无状态,服务端不存任何信息,水平扩展极其方便
  • 缺点:令牌签发后无法主动作废,想踢人必须加黑名单

2. 分布式 / 微服务支持

Session

  • 优点:简单、成熟
  • 缺点:多服务器必须共享 Session,架构复杂

JWT

  • 优点:天生支持分布式、微服务、跨域
  • 缺点:无

3. 跨域与前后端分离

Session

  • 优点:传统 Web 项目非常稳定
  • 缺点:Cookie 跨域限制大,不适合前后端分离、小程序、APP

JWT

  • 优点:完美支持跨域、APP、小程序、第三方 API
  • 缺点:前端需要手动存储并携带令牌

4. 性能与请求大小

Session

  • 优点:Cookie 很小,请求开销低
  • 缺点:每次请求都要查 Redis / 数据库

JWT

  • 优点:不用查库,验证极快
  • 缺点:令牌较长,Header 占用带宽稍大

5. 安全性

Session

  • 优点:信息存在服务端,不容易泄露
  • 缺点:依赖 Cookie,易受 CSRF 攻击

JWT

  • 优点:不依赖 Cookie,天然防 CSRF
  • 缺点:Payload 只是编码不是加密,不能放敏感信息
  • 一旦泄露,别人就能直接用(除非短过期 + HTTPS)

6. 令牌失效与管理

Session

  • 优点:想踢人就删 Session,实时生效
  • 缺点:无

JWT

  • 优点:无
  • 缺点:无法主动失效,必须靠过期或黑名单

7. 适用场景

Session

  • 传统 Web 网站
  • 单域名系统
  • 需要频繁踢人、强制下线的后台系统

JWT

  • 前后端分离(Vue/React)
  • APP、小程序
  • 微服务、API 开放平台
  • SSO 单点登录

三、优缺点总结表(最精简版)

表格

对比项Session-CookieJWT
状态有状态,服务端存储无状态,不存储
分布式支持差,需共享 Session极好,天然支持
跨域受 Cookie 限制不受限,适合前后端分离
主动失效容易,随时踢人困难,需过期或黑名单
性能需查库,略慢验证快,无需查库
安全风险CSRF令牌泄露风险,不能存敏感明文
实现复杂度简单,框架内置稍复杂,需处理令牌存储、刷新

四、一句话结论

  • 传统网站、后台管理系统 → 用 Session 更简单安全
  • 前后端分离、APP、小程序、微服务、API 授权 → 用 JWT 更合适

JWT 与 Session 认证流程对比图

我用纯文本流程图给你画最清晰、最直观的版本,一眼看懂核心差异!

一、传统 Session-Cookie 认证流程

[客户端]        提交用户名+密码          [服务端]
   │ ───────────────────────────────►   │
   │                                    │
   │                                    │ 验证账号密码
   │                                    │ 生成 Session 存储用户信息
   │                                    │ 生成 SessionID
   │ ◄───────────────────────────────   │
   │               返回 SessionID        │
   │
   │ 浏览器自动保存到 Cookie
   │
   │ 后续请求(自动携带 Cookie)
   │ ───────────────────────────────►   │
   │                                    │
   │                                    │ 根据 SessionID 查询 Session
   │                                    │ 验证通过 → 处理请求
   │                                    │
   │ ◄───────────────────────────────   │
   │               响应数据              │

核心特点

  • 服务端存数据,客户端只存一个 ID
  • 有状态,必须查会话库
  • 浏览器自动带 Cookie

二、JWT 认证流程

[客户端]        提交用户名+密码          [服务端]
   │ ───────────────────────────────►   │
   │                                    │
   │                                    │ 验证账号密码
   │                                    │ 生成 JWT(Header.Payload.Signature)
   │ ◄───────────────────────────────   │
   │                返回 JWT             │
   │
   │ 手动保存到 localStorage/Cookie
   │
   │ 后续请求(手动放在 Header)
   │ Authorization: Bearer <JWT>
   │ ───────────────────────────────►   │
   │                                    │
   │                                    │ 验证 JWT 签名 + 过期时间
   │                                    │ 无需查库 → 直接解析用户信息
   │                                    │
   │ ◄───────────────────────────────   │
   │               响应数据              │

核心特点

  • 服务端不存任何数据
  • 无状态,解析即认证
  • 客户端手动带令牌

三、一眼看懂最大区别

Session:服务端存信息 → 客户端拿ID查信息
JWT:服务端不存信息 → 客户端拿令牌直接用

需要我把这两张流程图做成面试可直接背诵的极简版吗?