JWT 身份认证优缺点分析
JWT 最大的卖点是无状态,最大的坑也是无状态——令牌发出去就收不回。存储位置同样不省心:localStorage 怕 XSS,Cookie 怕 CSRF。本文把 JWT 的优势、代价与适用边界摊开讲,并给出一份”什么时候不该用它”的清单。
它解决什么问题
Session-Cookie 方案里,会话状态保存在服务端,每个请求都要查一次存储,多实例部署还得解决会话共享。JWT 把身份声明签进令牌,服务端凭密钥自验,省掉中心化会话存储,天然适配多实例水平扩展、跨服务调用和移动端。这套设计在分布式系统里确实好用,但它不是免费的:状态被推到客户端的同时,服务端也放弃了对会话的即时控制权。分析 JWT 的优缺点,本质上是评估这笔交换在你的系统里划不划算。
核心原理:无状态这把双刃剑
优势一侧:
- 水平扩展:验签只需密钥,任意实例都能处理,扩容不用操心会话同步;
- 跨服务、跨端友好:令牌放在
Authorization头里,不受 Cookie 同源策略约束,微服务网关、单点登录都好落地; - 移动端友好:不依赖 Cookie,App 本地存储即可,也没有跨平台会话管理的麻烦。
代价一侧,全部来自同一个根源——服务端不存状态:
- 吊销困难:退出登录、封号、改密码,令牌在过期前照样有效;
- 权限滞后:用户角色调整了,旧令牌里固化的声明不会跟着变;
- 体积偏大:三段结构加 Base64URL 编码,比一个随机 SessionID 长得多,且每次都跟着请求走。
深入机制:存储位置之争
浏览器端令牌存在哪,是在两类风险之间做选择。
localStorage:押注 XSS 防线
Web Storage 里的令牌对同源页面的所有脚本可读。只要站点存在任何一处 XSS 注入点,恶意脚本就能把令牌直接打包外发。防 XSS 靠的是输出到 HTML、属性、JS、URL 等不同上下文时分别正确编码,再加 CSP 做纵深防御——但”全站绝无注入点”是个很难下保证的命题。好处是令牌不随请求自动发送,天然绕开了传统 CSRF。
Cookie:押注 CSRF 缓解
浏览器会自动携带 Cookie,于是有了 CSRF:攻击者诱导用户浏览器向目标站发起请求,Cookie 跟着走,服务端难辨真假。缓解手段是组合拳:HttpOnly(脚本读不到,挡住 XSS 窃取)、Secure(仅 HTTPS 传输)、SameSite=Lax/Strict(跨站请求不携带,挡住大部分 CSRF),敏感操作再叠加 CSRF Token 或 Origin/Referer 校验。SameSite 应视为纵深防御的一环,而不是唯一防线。
一句话总结:localStorage 把风险押在 XSS 上,Cookie 把风险押在 CSRF 上。CSRF 的缓解手段比”保证全站绝无 XSS”更可控,所以浏览器场景通常更推荐 HttpOnly Cookie,或者干脆用 BFF 架构把令牌留在服务端。
工程实践:什么系统不该用 JWT
- 需要即时踢人、精细会话控制的系统:后台管理、金融风控、异地登录检测这类场景,Session 或”不透明 token + Redis”删除即失效,比给 JWT 打补丁直接得多;
- 权限频繁变化的系统:声明签发即固化,改权限要等令牌过期,或被迫维护黑名单;
- 安全储备不足的团队:算法混淆、密钥轮换、刷新令牌重放检测,每个都是实打实的坑,不透明 token 的出错面小得多;
- 简单单体应用:Session-Cookie 成熟到不需要额外理由去替换。
反过来,开放平台 API、微服务间调用、SSO 的 ID Token——这些”签发方与消费方分离、令牌生命周期短”的场景,才是 JWT 的主场。另外,续期问题也不容忽视:推荐短寿命 access token 配合服务端管理、可轮换的 refresh token,而不是把令牌有效期拉到一整天。
对比与权衡
| 维度 | JWT | Session-Cookie |
|---|---|---|
| 服务端状态 | 无(除非加黑名单) | 会话存服务端或 Redis |
| 水平扩展 | 天然支持 | 需共享存储或粘滞会话 |
| 吊销能力 | 难,靠黑名单或等过期 | 删除会话即生效 |
| 跨域与移动端 | 友好 | 受 Cookie 策略限制 |
| CSRF 风险 | 放 Authorization 头则无 | 需 SameSite 加 Token 防护 |
| XSS 窃取风险 | 存 localStorage 则高 | HttpOnly Cookie 可缓解 |
| 请求体积 | 较大,数百字节起步 | 只有一个 SessionID |
面试视角
JWT 最大的缺点是什么?怎么缓解?
无状态导致无法即时吊销。缓解靠短寿命 access token 加可撤销的 refresh token,高危操作再配合 jti 黑名单;代价是重新引入服务端状态。
令牌存 localStorage 还是 Cookie?
localStorage 怕 XSS,脚本可直接读走;Cookie 怕 CSRF,但可用 HttpOnly、Secure、SameSite 加 CSRF Token 组合缓解。浏览器场景通常选后者,或直接上 BFF。
JWT 和 Session-Cookie 怎么选?
看三点:是否需要即时吊销、客户端形态是浏览器还是 App/第三方、令牌内权限是否频繁变化。要即时控制选 Session,跨域跨端、追求无状态扩展选 JWT。
用了 JWT 系统就无状态了吗?
不一定。一旦引入黑名单、刷新令牌存储、强制下线这些功能,服务端状态又回来了。JWT 只是让你可以把状态减到最少,而不是消灭状态。
小结
- JWT 的优点和缺点同源:无状态换来扩展性,同时失去即时控制。
- 存储之争没有银弹:localStorage 押注 XSS 防线,Cookie 押注 CSRF 缓解,后者更可控。
- 需要强会话控制的系统不该用 JWT;签发与消费分离、令牌短命的开放场景才是它的主场。
- 任何宣称”JWT 完全无状态”的生产方案,都值得追问一句:那你们怎么踢人下线?

