更新时间:2026年4月10日 | 本文是AI助手好用系列技术科普第一篇,后续将持续输出认证与授权方向的深度内容。
引言

JSON Web Token(简称JWT),是当前Web应用与微服务架构中最主流的无状态认证方案之一。无论是在前后端分离的SPA应用中,还是在分布式的微服务体系里,JWT几乎已经成为身份认证的标配。
然而很多学习者面临这样的困境:会用,但不懂原理;看过文档,但概念混淆;面试被问到,答不出层次。 本文将从痛点出发,逐步拆解JWT的诞生背景、核心结构、算法选择、代码实战、安全风险及面试考点,帮你建立完整的技术知识链路。

一、为什么需要JWT——Session认证的局限性
在JWT出现之前,Web应用最常用的认证方式是基于Session的认证。其工作流程如下:
用户登录,服务器验证凭证
服务器创建Session,将Session ID存入服务端存储(如内存、Redis)
服务器将Session ID通过Cookie返回给浏览器
后续请求浏览器自动携带Cookie,服务器根据Session ID查找到对应的会话信息完成认证
这套机制简单直观,但随着应用规模的扩大,问题逐渐暴露:
水平扩展困难:用户登录后Session落在某台服务器上,其他服务器无法获取,需要引入Redis等集中存储实现Session共享,增加了系统复杂度和网络开销。
服务端状态臃肿:每个在线用户都需要在服务端维护一份Session数据,百万级并发时内存消耗巨大。
跨域支持受限:Cookie的跨域特性不友好,在微服务架构中多个服务可能部署在不同域名下,Session机制难以天然适配。
即时注销困难:Session由服务端存储,可以立即删除实现注销,但这种“有状态”的设计与无状态的微服务理念背道而驰。
这些痛点催生了JWT的出现。JWT将用户身份信息直接编码在令牌中,服务端无需存储任何会话状态,实现了真正的无状态认证。
二、核心概念讲解:JWT是什么
标准定义
JWT(JSON Web Token,RFC 7519)是一个开放标准,定义了一种紧凑且自包含的方式,用于在各方之间安全地传输JSON对象-4。
拆解关键词:
紧凑(Compact) :JWT以字符串形式存在,体积小,适合在URL、HTTP Header、POST参数中传输
自包含(Self-contained) :JWT本身携带了所有必要的用户信息(如用户ID、角色、过期时间),服务端无需额外查询数据库
安全传输:通过数字签名保证令牌的完整性和真实性,防止被篡改
生活化类比
可以把JWT想象成一张带防伪印章的通行证。你去游乐园买票时,工作人员给你一张盖了章的票(签发JWT),票面上写明了你的入场有效期、可游玩区域等信息。之后每进一个项目,工作人员只看票面的印章和内容就放行,不需要打电话问售票处确认你是否真的买过票。JWT的签名就是这个“印章”,确保没人能在票面上涂改内容后还能蒙混过关。
JWT的结构
一个完整的JWT由三个Base64Url编码的部分组成,中间用点号分隔:
<header>.<payload>.<signature>1. Header(头部)
Header通常包含两个字段:令牌类型(typ)和签名算法(alg)。例如:
{ "typ": "JWT", "alg": "HS256" }
其中alg指定了签名所使用的加密算法,可以是HS256(对称加密)或RS256(非对称加密)等-1。
2. Payload(载荷)
Payload是JWT的核心内容,包含了需要传递的声明(Claims) 。声明分为三类:
注册声明:预定义的标准化字段,如
iss(签发者)、exp(过期时间)、sub(主题/用户ID)、iat(签发时间)公共声明:可自定义的声明,但建议在IANA JSON Web Token Claims注册表中登记以避免冲突
私有声明:双方约定自定义的信息
示例Payload:
{ "sub": "1234567890", "name": "John Doe", "iat": 1516239022, "exp": 1516242622, "role": "admin" }
重要提示:Payload仅经过Base64Url编码,并非加密。任何人都可以解码查看其内容,因此绝对禁止在Payload中存放密码、密钥等敏感信息-4-46。
3. Signature(签名)
签名是JWT防篡改的基石。它的生成方式为:将编码后的Header和Payload用点号拼接,再使用Header中指定的算法和密钥进行签名-1。
HMACSHA256( base64UrlEncode(header) + "." + base64UrlEncode(payload), secret )
签名的核心作用是验证消息的真实性和完整性:服务端收到JWT后,使用同样的密钥重新计算签名,与JWT附带的签名比对,若一致则证明令牌未被篡改。
三、关联概念讲解:HS256 vs RS256
JWT的签名算法主要分为两类:对称加密算法(HS系列) 和非对称加密算法(RS系列) 。
HS256(对称加密)
HS256全称为HMAC with SHA-256,使用同一个密钥进行签名和验证-10。
特点:
计算效率高,签名和验证速度快
实现简单,只需一个共享密钥
密钥必须在签名方和验证方之间共享
适用场景:集中式认证场景,即签名和验证都由同一可信方完成,例如单体应用内部的身份验证。
局限:任何拥有密钥的节点既能验证也能签发令牌。一旦密钥泄露,任意服务都可签发伪造的JWT。密钥轮换时需要重新部署所有依赖方-11-18。
RS256(非对称加密)
RS256全称为RSA Signature with SHA-256,使用私钥签名、公钥验证的非对称加密方式-10。
特点:
只有持有私钥的一方才能签发令牌,安全性更高
任意持有公钥的第三方都可以验证令牌真伪,无需共享敏感密钥
公钥可以通过JWKS(JSON Web Key Set)端点公开分发
行业普遍推荐使用RS256-18
适用场景:微服务架构、第三方API授权、多服务共享认证等分布式环境。
示例:Auth0等身份认证平台在签发JWT时使用私钥签名,各微服务只需通过公开的JWKS端点获取公钥即可验证令牌,不需要知道私钥。
四、概念关系与区别总结
| 对比维度 | HS256(对称) | RS256(非对称) |
|---|---|---|
| 密钥数量 | 1个(共享密钥) | 2个(私钥+公钥) |
| 签名方与验证方 | 必须相同/共享密钥 | 签名用私钥,验证用公钥 |
| 密钥泄露风险 | 高(密钥可被伪造令牌) | 低(公钥泄露不影响签名安全) |
| 计算性能 | 快 | 较慢(签名环节慢约两个数量级) |
| 密钥轮换复杂度 | 高(需重新部署所有依赖方) | 低(更换私钥,更新JWKS即可) |
| 推荐程度 | 适合集中式、内部系统 | 推荐用于分布式、微服务架构 |
一句话概括:HS256是“一家人共用一把钥匙”,RS256是“一家之主用私章盖章,大家用公开图章验真”。
五、代码示例:从签发到验证
以下使用Node.js的jsonwebtoken库,演示JWT的完整工作流程。
安装依赖
npm install jsonwebtoken签发Token(登录接口)
const jwt = require('jsonwebtoken'); const user = { id: 10001, username: 'alice', role: 'user' }; const SECRET = 'your-secret-key'; // 生产环境请使用环境变量 // 签发JWT,有效期1小时 const token = jwt.sign( { sub: user.id, // 用户标识 username: user.username, role: user.role, iat: Math.floor(Date.now() / 1000) // 签发时间 }, SECRET, { expiresIn: '1h' } ); console.log(token); // 输出: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOjEwMDAxLCJ1c2VybmFtZSI6ImFsaWNlIiwicm9sZSI6InVzZXIiLCJpYXQiOjE3NDQyNzUyMDAsImV4cCI6MTc0NDI3ODgwMH0.xxx
验证Token(受保护接口)
app.get('/api/profile', (req, res) => { const authHeader = req.headers.authorization; if (!authHeader) { return res.status(401).json({ error: '未提供Token' }); } // 标准格式:Bearer <token> const token = authHeader.split(' ')[1]; try { const decoded = jwt.verify(token, SECRET); // 验证通过,返回用户信息 res.json({ user: decoded }); } catch (err) { if (err.name === 'TokenExpiredError') { res.status(401).json({ error: 'Token已过期' }); } else { res.status(403).json({ error: 'Token无效' }); } } });
无状态刷新机制(Access Token + Refresh Token)
生产环境下,Access Token有效期通常设置为15分钟,配合长期有效的Refresh Token(7天)实现无感续签-39。
function generateTokens(user) { // Access Token:短有效期,用于访问资源 const accessToken = jwt.sign( { id: user.id, email: user.email }, process.env.JWT_ACCESS_SECRET, { expiresIn: '15m' } ); // Refresh Token:长有效期,仅用于换取新Access Token const refreshToken = jwt.sign( { id: user.id }, process.env.JWT_REFRESH_SECRET, { expiresIn: '7d' } ); return { accessToken, refreshToken }; }
刷新机制的核心设计原则:Refresh Token只能用于换取新的Access Token,不能直接作为资源访问凭证,以此缩短Token泄露的攻击窗口。
六、底层原理与技术支撑
JWT的安全性和功能性依赖于几个底层技术:
Base64Url编码:将JSON对象转换为URL安全的字符串,确保JWT可以在HTTP Header、URL参数等场景中无障碍传输。需要注意的是,编码≠加密,任何人都可以解码查看Payload内容。
数字签名算法:包括HMAC系列(对称)和RSA/ECDSA系列(非对称)。签名机制确保了JWT的完整性——任何对Header或Payload的修改都会导致签名验证失败。
声明(Claims)体系:
exp(过期时间)、nbf(生效时间)、iat(签发时间)、jti(唯一标识)等标准化字段,为令牌的生命周期管理和防重放提供了标准化基础。
正是这些底层技术的组合,赋予了JWT“无状态但可信”的核心特性。
七、安全攻击面与防护要点
1. alg: none 攻击
当服务端接受JWT Header中alg字段设置为none的令牌时,攻击者可绕过签名验证,任意篡改Payload内容,实现权限提升或用户身份伪造-55。2025年至2026年间,多个CVE漏洞(如CVE-2025-59934、CVE-2026-23993)均与此相关--。
防护措施:服务端必须在验证流程中拒绝所有alg: none的令牌,并严格校验Header中的算法是否与系统预设的白名单一致-2。
2. Token存储安全
将JWT存储在localStorage或sessionStorage中是最常见的错误实践——这些存储机制可通过JavaScript直接访问,一旦存在XSS漏洞,攻击者可读取并窃取Token-24。
最佳实践:
Web端优先使用HttpOnly Cookie存储JWT,使JavaScript无法读取Token,从根本上杜绝XSS窃取-22
若必须前端存储,建议采用BFF(Backend For Frontend)架构,将Token管理后置到服务端
移动端使用平台安全存储API:iOS使用Keychain,Android使用Keystore-24
3. Token泄露风险
JWT作为Bearer Token,任何持有者均可使用。若Token在网络传输中被拦截,攻击者可冒充用户。
防护措施:
强制使用HTTPS,防止中间人攻击
设置合理的
exp过期时间,Access Token建议不超过15分钟,即使泄露也能将损害窗口缩至最小-18敏感场景可结合mTLS或DPoP(Demonstrating Proof-of-Possession)实现发送者约束
八、高频面试题与参考答案
面试题1:JWT由哪几部分组成?每部分的作用是什么?
参考答案:JWT由三部分组成,用点号分隔:Header(头部)、Payload(载荷)、Signature(签名)。
Header:包含令牌类型(typ)和签名算法(alg),如
{"typ":"JWT","alg":"HS256"}Payload:包含声明信息(claims),如用户ID、过期时间、角色等业务数据
Signature:通过对Header和Payload使用指定算法和密钥签名生成,用于验证令牌的真实性和完整性
踩分点:答出三部分名称、各自内容、签名的作用是防篡改和验证真实性。
面试题2:JWT和Session认证有什么区别?各有什么优缺点?
参考答案:
| 维度 | Session认证 | JWT认证 |
|---|---|---|
| 服务端状态 | 有状态,需要存储Session | 无状态,无需存储 |
| 扩展性 | 需Session共享(Redis等) | 天生支持水平扩展 |
| 跨域支持 | 依赖Cookie,跨域复杂 | 通过Header携带,天然跨域 |
| 即时注销 | 可立即删除Session实现 | 需依赖黑名单或短过期时间 |
| 性能 | 每次请求需查Session存储 | 只需本地验证签名,无I/O开销 |
JWT适用于微服务架构、前后端分离、移动端等场景;Session适用于单体应用和对即时注销要求高的系统。
踩分点:对比维度完整,能结合场景说明各自适用条件。
面试题3:HS256和RS256有什么区别?如何选择?
参考答案:HS256是对称加密算法,使用同一密钥进行签名和验证;RS256是非对称加密算法,使用私钥签名、公钥验证。
选择建议:
HS256:适合集中式架构,签名方和验证方为同一可信服务,实现简单、性能高
RS256:推荐用于分布式架构和微服务,公钥可安全分发,私钥仅服务端持有,安全性更高,且密钥轮换更灵活
踩分点:区分对称/非对称,说清各自适用场景,明确RS256更推荐。
面试题4:JWT存在哪些安全风险?如何防范?
参考答案:
alg: none攻击:服务端必须拒绝
alg: none的令牌,严格校验算法白名单Token存储风险:Web端使用HttpOnly Cookie替代localStorage,防止XSS窃取
传输拦截风险:强制使用HTTPS加密传输
Token泄露滥用:设置短过期时间(如15分钟),配合Refresh Token机制减少泄露窗口
Payload信息泄露:不存放敏感信息(密码、密钥),因为Payload仅编码不加密
踩分点:至少答出3种以上风险及对应防范措施,体现安全意识。
九、总结
本文围绕JWT的完整知识链路,梳理了以下核心要点:
✅ 为什么需要JWT:Session机制在分布式场景下的扩展性瓶颈催生了无状态认证方案
✅ JWT是什么:由Header、Payload、Signature三部分组成的紧凑型自包含令牌
✅ 算法选择:HS256对称加密 vs RS256非对称加密,分布式场景推荐RS256
✅ 代码实战:签发、验证、刷新Token的完整流程
✅ 安全要点:拒绝
alg: none、禁用localStorage存储、强制HTTPS、设置短过期时间✅ 面试考点:JWT结构、与Session对比、HS256/RS256差异、安全风险与防范
易错提醒:JWT的Payload仅经过Base64编码而非加密,禁止存放密码等敏感信息;Token存储切不可直接使用localStorage。
本文是AI助手好用系列的第一篇。下一篇将继续深入探讨OAuth 2.0协议与JWT的配合使用,以及生产环境中的Token黑名单与密钥轮换实践,欢迎持续关注。