JWT 的 Payload 里,到底能不能放用户手机号?
JWT 由三段组成,形如 xxxxx.yyyyy.zzzzz:
第一类误区编码与加密混淆:前两段是 Base64URL 编码的 JSON(分别是 Header 与 Payload),第三段是 Signature。
关键在于 Base64URL 只是一种编码方式,不是加密------把 Payload 那一段贴进任何 Base64 解码器都能看到明文。
真正保证内容不被篡改的是 Signature:服务端用密钥或私钥对前两段计算签名,校验时重算并比对,Payload 只要被改过一个字符,签名验证就会失败。因此 JWT 的安全边界是"防篡改、不防读取",手机号、身份证号、密码等敏感信息不适合放进 Payload。
第二类误区在算法层:Header 里的 alg 声明本应只作参考,若服务端完全信任客户端传入的算法,攻击者把它改成 none(无签名)就可能伪造任意 Token,这类算法混淆漏洞的修复方式是服务端固定算法白名单,只接受预期的那一种。
第三类问题出在时间上:exp、iat、nbf 都是 Unix 秒级 时间戳,若按毫秒解析会得到 1970 年的日期,表现为"Token 明明没过期却被判失效"或反之。此外还要注意字符集差异:Base64URL 使用 - 和 _ 并去掉 = 填充,而标准 Base64 使用 + 和 / 并保留填充,用标准解码器去解 Base64URL 会直接失败。
下面以一个纯前端在线工具为例,演示 JWT 的结构解析、时间换算与算法识别。
一、工具简介
盘子工具站的JWT解析工具(打开工具)是一款在浏览器本地运行的令牌解析工具。JWT 令牌格式为 xxxxx.yyyyy.zzzzz(三段 Base64URL 用点分隔),所有解码在浏览器本地完成,不上传服务器。核心能力:

- 本地处理:所有计算在浏览器完成,数据不上传服务器
- Header 展示 :解析出头部字段,示例为
alg: HS256、typ: JWT,用于确认签名算法 - Payload 展示:解析声明字段,示例含 sub / name / iat / exp,并对有效期状态给出"有效"标注
- Signature 展示:单独列出签名段,便于确认令牌是否带签名
- 时间换算:把 exp、iat 等秒级时间戳换算成可读时间,示例为过期时间 2279-01-15 16:54:38、签发时间 2018-01-18 09:30:22
- 长度统计:给出 Header、Payload、Signature 与总长度的字符数,示例为 36 / 96 / 43 / 177 字符
- 算法与声明参考:页面附算法参考表与常见声明字段表,便于对照查阅
二、适用场景
- 联调排查:接口返回 401 时,先解析 Token 看 exp 是否已过期、sub 是否是预期的用户 ID
- 确认签名算法:拿到第三方下发的令牌,先看 Header 的 alg 是否与服务端校验配置一致
- 安全自查:检查 Payload 里是否混入了手机号、身份证等不该出现的敏感字段
- 跨端时间核对:前端把 exp 当毫秒处理导致误判过期,用时间换算结果对照确认单位
三、操作步骤
第一步: 打开 JWT解析工具,页面主体是令牌输入区,下方依次是 Header、Payload、Signature 三段的结果区,以及时间换算与长度统计区。

第二步: 粘贴待解析的 JWT。工具按三段 Base64URL 结构拆分,前两段解码为 JSON 对象,第三段作为签名原样展示。若解码失败,检查令牌是否被截断或是否被二次编码。

第三步: 查看 Header 区,确认 alg 与 typ 字段。示例数据为 alg: HS256、typ: JWT;确认算法后对照页面的算法参考表:HS256/HS384/HS512(HMAC with SHA-256/384/512,推荐)、RS256/RS384/RS512(RSASSA-PKCS1-v1.5,推荐)、ES256/ES384/ES512(ECDSA,推荐)、none(无签名,不安全)。


第四步: 查看 Payload 区,核对业务声明字段。示例中的 sub、name、iat、exp 会被逐条列出,有效期状态给出"有效"标注。字段含义不清楚时对照常见声明字段表:iss 签发者、sub 主题(通常为用户 ID)、aud 接收方、exp 过期时间、iat 签发时间、nbf 生效时间。

第五步: 查看时间换算结果,确认 exp 与 iat 换算出的可读时间是否符合预期。示例数据换算后为过期时间 2279-01-15 16:54:38、签发时间 2018-01-18 09:30:22。注意这两个声明的单位是 Unix 秒,不是毫秒。

第六步: 查看长度统计,工具给出 Header、Payload、Signature 与总长度的字符数,示例为 36、96、43、177 字符。长度异常偏小或签名段缺失时,需要确认令牌生成环节是否有问题。

四、功能亮点
- 三段结构分开展示:Header、Payload、Signature 独立成区,算法、声明、签名各自可查,不用自己按点号切字符串
- 时间自动换算:exp、iat 直接换算成可读日期时间,并标注有效期状态,避免把秒当毫秒造成的误判
- 本地解析不上传:令牌含业务身份信息,全程在浏览器内解码,不经过服务端
- 长度统计:给出各段与总长度的字符数,便于快速判断令牌是否完整
- 内置参考表:算法表标注了各算法的安全性(none 明确标注为不安全),声明字段表解释 iss / sub / aud / exp / iat / nbf 的含义
五、常见问题
Q:解析时会把 Token 上传到服务器吗?
不会。所有解码都在浏览器本地完成,令牌不会离开你的设备,因此业务环境的令牌也可以放心解析。
Q:支持哪些签名算法?
支持 HS256/HS384/HS512、RS256 等常见算法,页面算法参考表中还列出了 ES 系列与 none。需要注意 none 表示无签名,是不安全的,服务端校验时应固定算法白名单,不信任令牌自带的 alg。
Q:Payload 是加密的吗?
不是。Payload 只是 Base64URL 编码,任何人都能解码看到明文,安全性完全依赖 Signature 防篡改。因此不要在 Payload 中放置敏感信息。
Q:JWT 和 Session 有什么区别?
Session 在服务端存储状态,客户端 Cookie 里只放 Session ID,适合传统 Web 应用;JWT 把信息放在令牌里由客户端存储,服务端无需查库即可校验,适合 API 与微服务场景,无状态也更易于水平扩展。
Q:exp 和 iat 是什么单位?
都是 Unix 时间戳,单位是秒(不是毫秒)。按毫秒解析会得到 1970 年前后的日期,导致过期判断出错,这是跨端对接时最常见的时间类问题。
六、相关工具推荐
- 时间戳转换:核对 exp、iat 等秒级时间戳,或反查某个时间点对应的时间戳

- Base64编码解码:理解 Base64URL 与标准 Base64 的字符集差异,或手动验证某一段的解码结果

七、总结
- JWT 分 Header、Payload、Signature 三段,前两段是 Base64URL 编码的 JSON,可直接解码查看。
- Base64URL 不是加密,Payload 内容对任何人都可见,敏感信息不应写入;安全依赖 Signature 防篡改。
- 服务端不应信任令牌自带的 alg,需固定算法白名单,规避 alg=none 这类算法混淆风险。
- exp、iat、nbf 均为 Unix 秒级时间戳,单位搞错是过期判断异常的高频原因,核对时用时间换算结果对照。