JWT 技术(JSON Web Token) 全解:原理、应用与生产级避坑指南

笔者阅读很多 JWT 技术的博文,发现大多只是讲 “JWT 是什么”,而这篇文章重点介绍它为什么出现、结构细节、以及生产环境中最棘手的“注销与续签”问题。

在前后端分离、微服务架构大行其道的今天,JWT(JSON Web Token)几乎成为了身份认证的代名词。

很多开发者只知道它是一个“长长的字符串”,用来做登录校验,但并不清楚它内部的运作机制,以及它在安全性上的潜在风险。本文将从原理、结构、流程、以及最核心的生产陷阱四个维度进行详细拆解。

一、为什么需要 JWT?(Session vs Token)

在 JWT 出现之前,我们主要使用 Session + Cookie 的方式。

1.传统Session的认证痛点

  • 服务端有状态:服务端需要保存 Session 数据(内存或Redis)。
  • 扩展性差:集群环境下,必须做 Session 共享(如存入Redis),否则用户请求落到不同服务器会掉线。
  • 移动端支持差:原生 App 对 Cookie 的支持不如浏览器友好。
  • CSRF 风险:基于 Cookie 自动发送的特性,容易遭受跨站请求伪造攻击。

2.JWT(JSON Web Token)认证优势

  • 服务端无状态:服务器不保存任何会话数据,Token本身包含了用户信息和有效期。
  • 扩展性强:服务器拿到 Token 只要“解密/验签”即可,天然支持分布式、微服务。
  • 跨语言/跨端:JSON是通用的,且不依赖 Cookie ,适合 App、小程序、IoT 设备

一句话总结

Session 是把“通行证”存在服务器,给你个号码;JWT 是把“通行证”直接印发给你,服务器只负责查验真伪。

二、JWT 的结构解剖

一个标准的 JWT 字符串看起来是这样的:

xxxxx.yyyyy.zzzzz

它由 3 部分 组成,中间用 . 分隔:

1. Header(头部)

描述 Token 的元数据,通常包含两部分:

{ "alg": "HS256", // 签名算法,如 HMAC SHA256 或 RSA "typ": "JWT" // 令牌类型 } 

Base64Url 编码后,构成第一部分。

2. Payload(负载)

这是最核心的部分,存放有效信息(Claims)。包含标准字段和自定义字段:

{ "sub": "1234567890", // 用户ID "name": "John Doe", // 自定义字段 "admin": true, // 自定义字段 "iat": 1516239022, // 签发时间 "exp": 1516242622 // 过期时间 (非常重要) } 

Base64Url 编码后,构成第二部分。

生产高危警告
Payload 只是进行了 Base64 编码,并没有加密! 任何人拿到 Token 都能解码看到 Payload 内容。
绝对不要在 Payload 中放入密码、手机号等敏感信息!

3. Signature(签名)

1)Signature 的本质:消息摘要 + 密钥

Signature 的本质是一个 MAC(Message Authentication Code)

用密钥对一段消息做不可逆摘要

它同时解决两个问题:

  1. 完整性(Integrity):内容有没有被改
  2. 身份认证(Authenticity):是不是“我”签的

2)签名到底签了什么

以最常见的 HS256(HMAC + SHA256) 为例:

signature = HMACSHA256( base64UrlEncode(header) + "." + base64UrlEncode(payload), secret ) 
注意三个重点(面试/实战必考):
1. 被签名的是 Header + Payload
  • 不是只签 Payload
  • Header 里包含算法类型 alg
  • 改 Header 或 Payload 任意一个字节,签名都会失效
2. 使用的是 对称密钥(Secret)
  • 签名 & 验证使用同一个 Secret
  • 谁拿到 Secret,谁就可以:
    • 伪造 Token
    • 提权(admin: true)
3. 这是不可逆的
  • 无法从 Signature 推导出 Payload
  • 也无法从 Payload 推导出 Secret

3)一步一步看签名是如何生成的

假设我们有:

{ "alg": "HS256", "typ": "JWT" } 

Base64Url 编码后:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9 

Payload
{ "sub": "1001", "admin": false, "exp": 1700000000 } 

Base64Url 编码后:

eyJzdWIiOiIxMDAxIiwiYWRtaW4iOmZhbHNlLCJleHAiOjE3MDAwMDAwMDB9 

拼接待签名字符串
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9. eyJzdWIiOiIxMDAxIiwiYWRtaW4iOmZhbHNlLCJleHAiOjE3MDAwMDAwMDB9 

使用 Secret 做 HMAC
HMACSHA256(data, secret) 

得到 Signature:

Xk8Zk0gQZKZP6u9M1KxZPzXqZk8rQ2kR2WZc9F7d2Gs 

最终 JWT
Header.Payload.Signature 

4)为什么篡改 Payload 一定会失败?

假设黑客做了这件事:

{ "admin": false } ↓ { "admin": true } 

恶意攻击者能做到什么?

  •  能解码 Payload(Base64 是明文)
  •  无法生成新的合法 Signature

因为Secret 不在黑客手里

HMACSHA256(新Header + 新Payload, ???) 

服务器验证时做了什么?

服务器收到 Token 后会:

  1. 拆分 Header.Payload.Signature
  2. 使用自己的 Secret重新计算一次 Signature
  3. 对比:
    • 一致 → Token 没被改
    • 不一致 → Token 被篡改,直接 401
重点结论
JWT 的安全性完全依赖 Secret 是否泄露

三、标准认证流程

  1. 登录:用户提交用户名密码。
  2. 签发:服务端验证通过,生成 JWT(包含用户ID、过期时间等),返回给客户端。
  3. 存储:客户端收到 JWT,存储在 LocalStorage 或 Cookie 中。
  4. 请求:客户端再次发起请求时,在 HTTP Header 中携带:Authorization: Bearer <token>
  5. 验签:服务端拦截请求,解析 JWT,验证签名是否正确、是否过期。
    • 验证通过:放行,提取 Payload 中的用户 ID 进行业务逻辑。
    • 验证失败:返回 401 Unauthorized。

四、JWT 的致命缺陷与解决方案(生产级)

JWT 虽好,但它有一个核心缺陷:一旦签发,无法撤回(Stateless)

1. 无法强制登出(Logout 问题)

因为服务端不存状态,用户点击“注销”后,只要 Token 还没过期,如果被黑客截获,依然可以使用。

解决方案:

  • 黑名单机制(Blacklist):注销时将 Token ID ( jti == JWT ID ) 存入 Redis,设置过期时间等于 Token 的剩余有效期。每次校验时查一下 Redis。
    • 缺点:引入了状态,违背了 JWT 无状态初衷(但在生产中是必要的折中)。

2. 续签问题(Refresh Token)

JWT 过期时间设太长不安全,设太短用户体验差(老是需要重新登录)。

最佳实践:双 Token 机制

  • Access Token:有效期短(如 15 分钟),用于请求资源。
  • Refresh Token:有效期长(如 7 天),仅用于获取新的 Access Token。

流程:

  1. Access Token 过期,请求返回 401。
  2. 客户端自动携带 Refresh Token 请求 /refresh 接口。
  3. 服务端验证 Refresh Token 合法,返回新的 Access Token。
  4. 如果 Refresh Token 也过期了,强制用户重新登录。

五、JWT vs Session 对比总结

维度SessionJWT
状态存储服务端(内存/Redis)客户端(自带数据)
扩展性差(需 Session 共享)极好(无状态)
安全性防 CSRF 较麻烦,需防 Session 劫持需防 XSS,签名防篡改
RESTful不符合(有状态)符合(无状态)
性能需查库/查缓存CPU 计算签名(略耗 CPU)
注销容易(服务端删 Session)难(需黑名单机制)

六、安全避坑 Checklist

在生产环境使用 JWT,请务必检查以下几点:

  1. 必须使用 HTTPS:防止 Token 在传输过程中被中间人窃听。
  2. 算法安全:验证 Header 中的 alg,防止黑客将算法修改为 None(空算法攻击)。
  3. 不要存敏感数据:Payload 仅仅是 Base64 编码,谁都能看。
  4. 密钥保管:Secret 是命根子,绝对不能硬编码在代码里,要放在环境变量或配置中心。
  5. 存储位置
    • 建议存 HTTPOnly Cookie(防 XSS,但需处理 CSRF)。
    • 存 LocalStorage(方便,但容易被 XSS 攻击读取)。

 JWT 规范:RFC 7519

以上就是笔者对于 JWT 技术的讲解,如有错误,欢迎指正!

Read more

Android集成WebRTC与VAD的AI辅助开发实战:从选型到性能优化

快速体验 在开始今天关于 Android集成WebRTC与VAD的AI辅助开发实战:从选型到性能优化 的探讨之前,我想先分享一个最近让我觉得很有意思的全栈技术挑战。 我们常说 AI 是未来,但作为开发者,如何将大模型(LLM)真正落地为一个低延迟、可交互的实时系统,而不仅仅是调个 API? 这里有一个非常硬核的动手实验:基于火山引擎豆包大模型,从零搭建一个实时语音通话应用。它不是简单的问答,而是需要你亲手打通 ASR(语音识别)→ LLM(大脑思考)→ TTS(语音合成)的完整 WebSocket 链路。对于想要掌握 AI 原生应用架构的同学来说,这是个绝佳的练手项目。 从0到1构建生产级别应用,脱离Demo,点击打开 从0打造个人豆包实时通话AI动手实验 Android集成WebRTC与VAD的AI辅助开发实战:从选型到性能优化 移动端实时语音处理一直是个技术难点。根据实测数据,普通Android设备处理16kHz采样率的音频流时,仅WebRTC基础通话就会占用12-15%的CPU资源,如果再加上VAD检测,CPU占用可能飙升到25%以上。更棘手的是,从麦克风采集到

高性能OCR落地利器|DeepSeek-OCR-WEBUI开源实践

高性能OCR落地利器|DeepSeek-OCR-WEBUI开源实践 1. 引言:OCR技术的工程化挑战与新解法 在数字化转型加速的背景下,光学字符识别(OCR)已成为文档自动化、信息提取和智能审核等场景的核心技术。然而,传统OCR方案在面对复杂版面、模糊图像或多语言混合文本时,往往表现不佳,且部署流程繁琐,严重制约了其在实际业务中的广泛应用。 DeepSeek-OCR 的出现为这一难题提供了全新思路。作为一款基于深度学习的大模型驱动OCR系统,它不仅具备高精度、强鲁棒性的识别能力,更通过 DeepSeek-OCR-WEBUI 这一开源项目实现了“零代码+网页端交互”的极简使用模式。本文将围绕该镜像的技术特性、部署流程与核心功能展开详细解析,帮助开发者快速掌握其工程化落地方法。 2. 技术架构解析:DeepSeek-OCR的核心优势 2.1 模型设计原理 DeepSeek-OCR 采用 CNN + Transformer注意力机制 的混合架构: * 前端卷积网络(CNN) 负责图像特征提取,对倾斜、模糊、低分辨率等退化图像具有良好的适应性; * 中段序列建模模块 利

ofa_image-caption代码实例:扩展支持WebP格式与EXIF元数据保留功能

ofa_image-caption代码实例:扩展支持WebP格式与EXIF元数据保留功能 1. 引言 你有没有遇到过这种情况?从手机或相机里导出一堆照片,想快速整理归档,却要一张张手动写描述,费时又费力。或者,在做内容创作时,需要为大量图片配上精准的英文说明,人工处理效率极低。 今天要介绍的这个工具,就是来解决这个痛点的。它叫 ofa_image-caption,是一个纯本地运行的图像描述生成工具。简单来说,你给它一张图,它就能用英文告诉你这张图里有什么。 这个工具的核心是基于一个叫 OFA 的模型,这个模型在图像描述生成领域表现很不错。我们之前发布的版本已经能很好地处理 JPG、PNG 这些常见格式了。但最近,越来越多的用户开始使用 WebP 这种更高效的图片格式,同时,很多摄影师和内容创作者也希望生成的描述能保留图片拍摄时的原始信息(比如拍摄时间、相机型号)。 所以,我们对这个工具进行了一次重要的升级。这篇文章,我就带你手把手看看,我们是如何在原有代码基础上,扩展了对 WebP 格式的支持,并实现了 EXIF 元数据的保留功能。

零代码体验!BAAI/bge-m3 WebUI一键分析文本相似度

零代码体验!BAAI/bge-m3 WebUI一键分析文本相似度 1. 为什么你需要一个“不用写代码”的语义相似度工具? 你有没有遇到过这些场景: * 写完一段产品文案,想确认它和竞品描述是否太雷同? * 做知识库检索时,发现用户搜“怎么重置密码”却没召回“忘记登录密码怎么办”这条答案? * 客服机器人总把“退款”和“换货”当成一回事,导致工单分错类? * 教育平台里,学生提交的简答题答案五花八门,人工批改耗时又难统一标准? 这些问题背后,本质都是同一个技术需求:判断两段文字在意思上到底有多像——不是看字面是否重复,而是理解它们表达的语义是否一致。 传统方法靠关键词匹配、编辑距离或TF-IDF,结果常常很尴尬: “苹果手机续航差” 和 “iPhone电池不耐用” → 应该高分 但关键词完全不重合,TF-IDF打0.1分,系统直接忽略 这时候,就需要真正懂“意思”的模型。而BAAI/bge-m3,正是当前开源领域中少有的、能稳定处理中文长句+