免费工具 JWT 在线解析:解码载荷,本地验签
粘贴一个 JWT,马上看到头部和载荷,exp、iat、nbf 自动换算成北京时间,过没过期一眼就知道。填上密钥或公钥,还能在浏览器里验签。只解码不能证明 token 是谁签发的,页面每次都会明确告诉你这一点。
- 解码 + 验签
- 过期时间换成北京时间
- token 和密钥不出浏览器
JWT 解码与验签
示例 token 在 2026-11-10 09:00(北京时间)签发、一小时后过期,所以显示「已过期」。点「填入示例密钥」可以验签;也可以试试带公钥的 RS256 示例。
粘贴完整的 token。Bearer 前缀、引号和换行会自动去掉。
HS256/384/512 填共享密钥;RS、PS、ES、EdDSA 填 PEM 公钥、X.509 证书、JWK 或 JWKS。不要把私钥粘到这里,也不要粘到任何网站。
检查结果
过期、算法、签名和常见风险。
- 提示签名算法 HS256(HMAC)。
- 错误已过期(前天,exp 为 2026-11-10 10:00:00),服务端会拒绝它。
- 提示从 iat 到 exp 的有效期:1 小时。
- 提示时间按 Asia/Shanghai 显示。
- 提示只解码,未验签。任何人都能造一个带这些内容的 token,只有验签才能证明是谁签发的。在上面填入密钥或公钥即可验证。
{
"alg": "HS256",
"typ": "JWT"
}用什么算法签名、用哪把密钥(kid)。
{
"iss": "https://auth.example.cn",
"sub": "u_10086",
"aud": "api.example.cn",
"iat": 1794272400,
"exp": 1794276000,
"scope": "read:reports",
"nickname": "小明"
}拿到 token 的任何人都能看到这些内容。
sHCFpi1rHyRGAL_fjtqGXcLOGnUVq7YZtexhiNXenII
hex (32 bytes):
b07085a62d6b1f244600bfdf8eda865dc2ce1a7515abb619b5ec6188d5de9c82token 里的 Base64URL 原文,以及十六进制的原始字节。
声明逐项解读
注册声明排在前面(RFC 7519 第 4.1 节)。时间按你浏览器的时区显示。
| 声明 | 值 | 含义 | 状态 |
|---|---|---|---|
iss | https://auth.example.cn | 签发方:谁创建并签名了这个 token | — |
sub | u_10086 | 主体:通常是用户 ID | — |
aud | api.example.cn | 受众:token 给谁用 | — |
exp | 1794276000 → 2026-11-10 10:00:00 (前天) | 过期时间 | 已过期 |
iat | 1794272400 → 2026-11-10 09:00:00 (前天) | 签发时间 | — |
scope | read:reports | 授予的权限(空格分隔) | — |
nickname | 小明 | 自定义声明 | — |
版本 v1.0更新于 更新记录
三段内容,一条原则
JWT 由「头部.载荷.签名」三段组成,每段都是 Base64URL 编码。前两段只是 JSON,第三段才让 token 可信。
头部
alg 是签名算法,typ 是 token 类型,kid 说明用哪把密钥。服务端应该自己决定接受什么算法,而不是照单全收这个字段。
载荷
声明(claims):这个 token 是关于谁的(sub)、谁签发的(iss)、给谁用的(aud)、什么时候过期(exp)。它只是编码,没有加密。
签名
用密钥(HS)或私钥(RS、PS、ES、EdDSA)对前两段计算出来。载荷改一个字符,签名就对不上了。
解码不等于验证
谁都能写一个带任意声明的 token。签名用签发方的密钥验证通过、exp、aud、iss 也符合预期之前,载荷里的内容都只能当不可信的输入。
本页用浏览器自带的 Web Crypto 验签,token 和密钥不会发到任何地方。但线上的 token 在过期前就像密码一样,尽量用测试 token;生产 token 粘到不受你控制的网站后,应该让它失效。
三步
先解码,再验签。
-
1
粘贴 token
从请求头 Authorization、Cookie 或小程序 / App 的登录接口返回里复制过来,头部、载荷和声明表马上出来。
-
2
看检查结果
已过期、未生效、没有 exp、alg 为 none、载荷里有手机号邮箱,都会逐条用白话说明。
-
3
填密钥验签
HS 算法填共享密钥;RS、PS、ES、EdDSA 填签发方的公钥、证书或 JWKS。结果会替换「正在验证签名…」那一条。
注册声明和服务端怎么校验
RFC 7519 第 4.1 节注册了 7 个声明名,都是可选的,但签发 token 的服务几乎都会带上 iss、sub、exp、iat。时间是 NumericDate:从 1970-01-01 UTC 起的整秒数,不是毫秒,也不是北京时间。
- 签名输入是
BASE64URL(头部) + "." + BASE64URL(载荷),不带 = 填充(RFC 7515 第 7.1 节) - HS256 是 HMAC-SHA256,密钥至少 32 字节;RS256 是 RSASSA-PKCS1-v1_5;PS256 是 RSA-PSS;ES256 是 P-256 曲线 ECDSA,签名固定 64 字节(RFC 7518 第 3 节)
- 服务端应该固定期望的算法,并拒绝
none(RFC 8725)。Java 的 jjwt、Node 的 jsonwebtoken 等库都可以指定允许的算法 - 五段的 token 是加密的 JWE,只有接收方的私钥能解开
| 声明 | 名称 | 类型 | 服务端检查什么 |
|---|---|---|---|
iss | 签发方 | 字符串或网址 | 等于你信任的签发方 |
sub | 主体 | 字符串 | token 是关于谁的,常是用户 ID |
aud | 受众 | 字符串或数组 | 包含你这个服务的标识 |
exp | 过期时间 | 1970 年起的秒数 | 当前时间早于 exp(允许少量时钟误差) |
nbf | 生效时间 | 1970 年起的秒数 | 当前时间不早于 nbf |
iat | 签发时间 | 1970 年起的秒数 | 不在未来;用来算 token 年龄 |
jti | JWT ID | 字符串 | 没见过(需要防重放时) |
把示例 token 拆开看
本页默认的 token 逐段解码。签名用 Node.js 的 crypto.createHmac 生成,用示例密钥能验证通过。
| 部分 | 开头 | 解码后 | 说明 |
|---|---|---|---|
| 头部 | eyJhbGciOiJIUzI1NiIs… | {"alg":"HS256","typ":"JWT"} | HMAC-SHA256,共享密钥 |
| 载荷 | eyJpc3MiOiJodHRwczov… | "sub":"u_10086"、"iat":1794272400、"exp":1794276000、"nickname":"小明" | 2026-11-10 09:00(北京时间)签发,有效 1 小时;中文按 UTF-8 解出 |
| 签名 | sHCFpi1rHyRGAL_f… | 32 字节 | 只有示例密钥能对上 |
| 结论 | — | 签名有效,但已过期 | 服务端会返回 401 |
把载荷改一个字母再粘回来:声明照样能解出来,验签却会失败。这正是签名的意义,也是「只解码不够」的原因。
JWT 常见的坑
大多数 JWT 事故不是密码学被攻破,而是少做了校验。
只解码不验签
不验签就从 token 里读 sub、role,任何人都能伪造身份。先验签,再检查 exp、aud、iss。
相信头部里的 alg
接受 none,或者把 RS256 的公钥当成 HMAC 密钥来验,都是经典的伪造手法。每把密钥固定一种算法(RFC 8725)。
载荷里放敏感信息
载荷只是 Base64URL,手机号、邮箱、身份证号放进去,日志、浏览器存储里拿到 token 的人都能看到。
exp 写成了毫秒
exp 的单位是秒。直接写 Date.now() 或 Java 的 System.currentTimeMillis(),大多数库会认为它几万年后才过期。
用用户 ID 识别用户,而不是 token
用户登录后,你的系统已经知道他是谁,通常就是 token 里的 sub。统计需要的是这个 ID,而不是 token 本身。
JWT 怎么在线解析?
把 token 粘进来就行。头部和载荷是 Base64URL 编码的 JSON,马上就能解开;声明表会解释每个字段,并把 exp、iat、nbf 换算成北京时间(按你浏览器的时区)。解码不需要密钥。
在线解析 JWT 安全吗?会上传吗?
本页的解码和验签都在你的浏览器里完成,不上传,token 和密钥也不会写进任何链接。不过线上 token 在过期前就像密码,尽量用测试 token;生产 token 粘到不受你控制的网站后,应该让它失效。
解码 JWT 就等于验证了吗?
不是。解码只是读出 Base64URL 文本,任何人都能造一个带任意声明的 token。验证要用签发方的密钥或公钥检查签名,再检查 exp、nbf、aud、iss。在那之前,载荷内容都不可信。
怎么验证 JWT 签名?
在第二个框里填密钥。HS256、HS384、HS512 填共享密钥(拿到的是 Base64 就勾选对应选项);RS、PS、ES、EdDSA 填公钥,可以是 PEM、X.509 证书、JWK,或者 JWKS(会按 kid 自动挑出对应的那把)。
密钥是对的,为什么还提示签名无效?
常见原因:密钥是 Base64 编码的、需要先解码;密钥里混进了空格或换行;token 复制时被截断或改动;服务端实际用的不是你以为的那把密钥(看 kid)。另外,RS256 的 token 永远不能用 HMAC 密钥验证。
JWT、JWS、JWE 有什么区别?
JWT 是一组声明。日常见到的 JWT 几乎都是 JWS:三段、有签名、谁都能读。JWE 是五段,载荷加密了,只有接收方能解。本工具解码和验证的是 JWS。
token 刚签发就提示过期,怎么回事?
多半是时间问题:验证方和签发方的服务器时钟不一致;或者 exp 写成了毫秒、写成了北京时间的本地数字,而不是从 1970 年起的 UTC 秒数。对照声明表里的 exp 和 iat 看看。