JWT 是什么?JWT 结构、解析与登录鉴权详解
JWT 把身份声明打包成一个可自验证的字符串,让服务端不必保存会话就能确认”你是谁”。但便利背后有几个高频坑:Payload 只编码不加密、令牌签发后难以收回。本文从三段结构讲起,把签名原理、认证流程与吊销方案说透。
它解决什么问题
传统 Session 认证里,服务端要为每个在线用户保存一份会话,请求来了先查库或 Redis 才能确认身份;多实例部署还得解决会话共享问题。JWT 的思路是把身份信息和有效期写进令牌本体,再用密码学签名防篡改:任何持有密钥的服务都能独立完成校验,不需要中心化的会话存储,水平扩展、跨服务调用和移动端接入都随之简化。代价则是令牌在过期前始终有效,服务端失去了”一键踢人”的天然能力。
核心原理
三段式结构
JWT 形如 xxxxx.yyyyy.zzzzz,点号分隔三段,前两段是 JSON 经 Base64URL 编码的结果:
- Header(头部):元信息,主要是令牌类型
typ和签名算法alg; - Payload(载荷):承载声明(Claims),如
sub(用户标识)、exp(过期时间)、iat(签发时间)、iss(签发方)、aud(接收方)及业务自定义字段; - Signature(签名):对前两段拼接结果做的密码学签名,用来发现任何改动。
{ |
这个 Header 编码后就是令牌第一段,完整令牌长这样:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9. |
签名如何生成与校验
签名输入是编码后的 Header、Payload 和密钥,以 HS256 为例:
HMACSHA256( |
服务端收到令牌后,用同样的算法和密钥对前两段重算签名,再与第三段做恒定时间比较。攻击者改了 Payload 里任何字符,都算不出匹配的签名——除非密钥泄露。这就是”防篡改”的全部含义。
关键认知:编码不等于加密
Base64URL 只是可逆编码,任何人拿到令牌都能解出前两段的明文。签名保护的是完整性,不是机密性,密码、手机号、身份证这类敏感信息绝不能放进 Payload。同理,能解析(decode)出内容不代表令牌可信——必须先验签,再校验 exp、nbf、iss、aud,全部通过才能采信。
深入机制
HS256 vs RS256:对称与非对称
- HS256(HMAC-SHA256):同一把密钥签名和验签。部署简单、计算快,但每个能验签的服务都能伪造令牌,密钥在任一节点泄露即全线失守。
- RS256(RSA-SHA256):私钥签名、公钥验签。验签方只持公钥,无法签发新令牌,密钥分发面大幅缩小,适合微服务、第三方接入和密钥轮换场景;代价是签名验签慢一个数量级,且要维护公钥分发机制(如 JWKS 端点)。
选型经验:签发与消费在同一信任边界内,HS256 够用;签发方与验证方分离,选 RS256 或 ES256。
完整认证流程
- 客户端提交用户名密码,服务端校验通过后签发 JWT;
- 客户端保存令牌,后续请求放在
Authorization: Bearer <token>头中; - 服务端按
kid取对应密钥,先验签,再校验exp、nbf、iss、aud; - 全部通过后用
sub建立用户上下文,授权层再结合具体资源判断权限。
注意:JWT 只证明”签发时刻声明是真的”。用户此后被禁用或权限调整,令牌不会感知,业务层仍需处理。
工程实践
吊销难题与两种主流解法
JWT 发出后到过期前天然有效,退出登录、封号、改密码都不会让它立即失效。两种主流补救:
- 短有效期 + 刷新令牌:access token 只活 15~30 分钟,泄露窗口小;另发长寿命的 refresh token 用于换新,由服务端管理、可撤销可轮换。这是业界事实标准。
- 黑名单:把被吊销令牌的
jti写入 Redis,过期时间设为剩余寿命,验签先查黑名单。能即时吊销,但每次请求多一次查询,等于部分放弃无状态。
实践中常两者结合:常态靠短令牌压缩风险窗口,高危操作再写黑名单兜底。
其他必做项
- 服务端固定算法白名单,绝不信任令牌自报的
alg,拒绝none,防 HS256/RS256 算法混淆攻击; - 全程 HTTPS;Payload 只放最小必要声明,控制令牌体积;
- 使用成熟开源库完成签发与验签,不手写密码学逻辑;时钟偏差留 30~60 秒容忍,密钥按
kid轮换。
对比与权衡
| 维度 | HS256(对称) | RS256(非对称) |
|---|---|---|
| 密钥形态 | 共享密钥,签名验签通用 | 私钥签名,公钥验签 |
| 验签方能力 | 持有密钥即可伪造令牌 | 只有公钥,无法签发 |
| 性能 | 快,HMAC 开销极小 | 慢约一个数量级 |
| 适用场景 | 单体或同一信任域内 | 微服务、跨组织、公钥轮换 |
| 密钥泄露影响 | 任一验证节点泄露即全线失守 | 只需死守签发方私钥 |
面试视角
JWT 的三段结构是什么?签名防什么?
Header 记算法与类型,Payload 放声明,Signature 是对前两段的密码学签名。签名防篡改不防窃听:前两段只是编码,谁都能解开,敏感信息不能入 Payload。
HS256 和 RS256 怎么选?
签发与验证在同一信任域内,用 HS256 简单高效;两者分离(微服务、开放 API)时用 RS256,验证方只拿公钥,私钥泄露面最小。
用户退出登录后 JWT 还有效,怎么办?
根源是无状态。主流做法是短寿命 access token 加可撤销的 refresh token,需即时生效的场景(封号、改密)再把 jti 写进 Redis 黑名单。只发长令牌又不留任何服务端记录,是典型设计缺陷。
能解码出 Payload 就说明令牌可信吗?
不能。解码不需要密钥,任何人都能做,不含任何信任。必须先验签,再校验 exp、iss、aud 等声明,全部通过才能采信。
小结
- JWT 用”自包含声明 + 签名”换取服务端无状态,本质是拿吊销能力换扩展性。
- 三段结构里只有签名参与密钥运算;Base64URL 是编码不是加密,Payload 视同明文。
- HS256 与 RS256 的分野在于验签方是否可信;跨信任边界一律上非对称算法。
- 生产可用的 JWT 体系 = 短有效期 + 刷新令牌 + 算法白名单 + HTTPS,即时吊销再叠加黑名单。

