JWT

解码、签名并验证 JSON Web Token

正在加载工具…

关于 JWT 解码、生成与验签

JWT 解码、生成与验签工具会把令牌拆成头部和载荷,把时间声明渲染成可读时间戳,用你提供的密钥验证签名,也能签出一个用于测试的令牌。解码完全不需要密钥——这是关于这个格式最重要的一件事。

JSON Web Token 是用点连接的三段 Base64URL:声明算法的头部、装着声明的载荷,以及对前两段的签名。前两段是编码而非加密,任何拿到令牌的人都能读出里面的每一个声明。签名能证明的东西很窄但很有价值:签发者持有密钥,且两段内容此后没被改过。至于签发者是不是你期待的那个、受众对不对、是否还在有效期内,都属于你的应用仍然要做的策略校验。

如何使用这个开发者工具

  1. 选择「解码」查看令牌、「验签」校验签名,或「签名」用一段载荷造一个测试令牌。
  2. 把令牌粘进左侧面板;签名模式下,这个面板放的是声明 JSON。
  3. 验签和签名时先选与令牌头部一致的算法,再选密钥格式:HS 系列可选文本、Base64 或十六进制,RS、PS、ES、EdDSA 则用 PEM 或 JWK。
  4. 把共享密钥或密钥内容粘进面板下方的密钥框。
  5. 执行操作并阅读结果:解码会额外给出 timeClaims 区块,把 iat、nbf、exp 转换成 ISO 时间戳。

实例:不用密钥也能解码

一个真实的 HS256 令牌。没有提供任何密钥,所有声明照样可读——这正是重点所在。

令牌
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkRldiBUb29scyIsInJvbGUiOiJlZGl0b3IiLCJpYXQiOjE3NzAwMDAwMDAsImV4cCI6MTc3MDAwMzYwMCwiaXNzIjoiaHR0cHM6Ly9hdXRoLmV4YW1wbGUuY29tIiwiYXVkIjoiYXBpOi8vcmVwb3J0cyJ9.eJqfDF6kCs5lS3B-IoYdxY4V5azCgcxZStnJtWQl3Nc
解码结果
{
  "header": {
    "alg": "HS256",
    "typ": "JWT"
  },
  "payload": {
    "sub": "1234567890",
    "name": "Dev Tools",
    "role": "editor",
    "iat": 1770000000,
    "exp": 1770003600,
    "iss": "https://auth.example.com",
    "aud": "api://reports"
  },
  "timeClaims": {
    "iat": "2026-02-02T02:40:00.000Z",
    "exp": "2026-02-02T03:40:00.000Z"
  }
}

role 声明是在没有任何密钥的情况下读出来的,所以截图或日志里的一个令牌,就等于把它装的东西全都泄露了。timeClaims 还显示这个令牌在签发一小时后就过期了:今天拿去验签会先卡在 exp 时间检查上,签名结果根本轮不到。

注册声明与头部参数

RFC 7519 里的这些声明在规范上是可选的,在工程上是必需的。最后两行是头部参数而不是声明。

名称含义类型该怎么校验
iss签发者字符串或 URI必须与你配置的签发者完全一致
sub主体字符串principal,在该签发者范围内唯一且稳定
aud受众字符串或数组你的服务必须在其中,否则拒绝
exp过期时间Unix 秒过了这一刻即拒绝,允许少量时钟偏差
nbf生效时间Unix 秒早于这一刻即拒绝
iat签发时间Unix 秒可用于限制令牌年龄和重放窗口
jtiJWT 标识字符串唯一 ID,是做一次性使用追踪的抓手
alg算法(头部)字符串服务端固定期望值,绝不从令牌里取
kid密钥 ID(头部)字符串用于从 JWKS 文档中选出对应密钥

常见问题排查

令牌能解码,验签却提示签名校验失败。

成因 问题几乎总出在密钥而不是令牌上。以 Base64 或十六进制保存的共享密钥,被当成纯文本输入时得到的是另一串字节;复制时带上的结尾换行同样会改变密钥。

解决办法 把密钥格式选择器调成密钥实际的存储形式:文本、Base64 或十六进制。再核对一下你粘贴的密钥字节长度与签发服务配置的是否一致。

验签报「算法不被允许」。

成因 你选的算法和令牌头部里的 alg 不一致,而验签是刻意只允许你指定的那个算法。

解决办法 先解码令牌读出 header.alg,再选完全相同的算法。在自己的服务里也要把允许的算法固定在服务端——照单全收头部声明的算法,正是 JWT 最经典的漏洞。

别处能用的密钥,在这里验不了 RS256 令牌。

成因 验签需要 SPKI 形式的 PEM 公钥(以 BEGIN PUBLIC KEY 开头)或 JWK。证书、以 BEGIN RSA PUBLIC KEY 开头的 PKCS#1 公钥,以及私钥,都无法作为验签密钥导入。

解决办法 用 openssl x509 -in cert.pem -pubkey -noout 提取公钥;或者从提供方的 JWKS 文档里复制对应的 JWK 对象,并把密钥格式选成 JWK。

身份提供商发的令牌根本解不开。

成因 它不是签名 JWT。五段的令牌是加密的 JWE,而很多提供商签发的是看起来像随机串的不透明引用令牌。另外,从 URL 里复制的值可能还带着百分号编码。

解决办法 数一数点:两个点才是这里能解码的 JWS。带百分号编码的值先用 URL 工具解码。不透明令牌只能通过提供商的 introspection 接口查看。

验签通过了,API 还是拒绝这个请求。

成因 签名有效并不说明签发者、受众、作用域或吊销状态没问题。API 执行的是签名校验覆盖不到的策略。

解决办法 把 iss 和 aud 与 API 的期望值比对,确认所需的 scope 或角色存在,再确认令牌没有在服务端被吊销。

适合用这个工具的场景

  • 不用向任何人要密钥,就读出 bug 报告里附带的令牌到底装了什么。
  • 把 exp、nbf、iat 转成可读时间,解释会话为什么在那个时刻结束。
  • 对接联调时,确认某个公钥或 JWKS 条目确实能验证提供商签发的令牌。
  • 生成声明结构符合应用预期的测试令牌,包括故意造一个已过期的。

应该换用别的工具的场景

  • 任何涉及生产签名密钥的操作。这类密钥应当留在密钥管理服务里,并在那里完成签名。
  • 判断一个令牌是否可信。这需要签发者、受众、作用域和吊销策略,都不在签名校验的覆盖范围内。
  • 阅读加密的 JWE 令牌或提供商的不透明令牌,它们都不是签名 JWT,离开提供商就无法解读。

隐私与数据处理

解码、验签和签名都在当前浏览器标签页内通过 Web Crypto API 完成;你粘贴的密钥只存在于页面内存中,离开页面即销毁,全程不上传。但这只是关于传输的陈述,不是关于暴露面的保证:生产环境的签名密钥永远不该离开持有它的系统,能用测试密钥和脱敏令牌时就用它们。

相关开发者工具

常见问题

解码 JWT 等于验证它吗?

不等于。解码只是还原 Base64URL 再解析 JSON,任何人不用密钥都能做。验签则要用密钥和固定的算法重新校验签名,只有到那一步,声明才开始有意义。

既然谁都能读载荷,凭什么他们改不了?

凭签名。头部或载荷改一个字符签名就失效,伪造新签名则必须有密钥。整个安全模型就建立在这上面,这也是绝不能盲目相信 alg 头部的原因。

支持哪些密钥格式?

HS256 / HS384 / HS512 接受文本、Base64 或十六进制形式的共享密钥。RS、PS、ES、EdDSA 系列在签名时用 PEM 私钥、验签时用 PEM 公钥,两个方向也都支持 JWK 对象。

能直接填 JWKS 地址来验签吗?

不能,工具从不发起网络请求。请自己打开提供方的 JWKS 文档,复制 kid 与令牌头部匹配的那一个 JWK 对象,把密钥格式选成 JWK 后粘贴进来。

为什么还能生成 alg 为 none 的令牌?

因为它是个有用的测试用例。alg 为 none 的令牌完全没有签名;任何接受它的服务都存在漏洞,而造一个这样的令牌是验证你的服务不接受它的最快方式。

个人信息可以放进 JWT 吗?

不要放。载荷对任何拿到令牌的人都是可读的,包括浏览器扩展、代理日志,以及任何记录 URL 的环节。声明里只放标识符和授权事实。