工具
指南

JWT 解码器

开发

解码 JSON Web Token(header、payload)并查看其过期时间与签名。仅解码——不校验签名。

100% 客户端 无后端
头部(Header)
 
载荷(Payload)
 
签发时间(iat)
生效时间(nbf)
过期时间(exp)
签名(Signature)
本页内容

什么是 JWT?#

JWT(JSON Web Token,定义于 RFC 7519)是一种紧凑、URL 安全的令牌,用来在双方之间携带”声明”(claims)。它就是你登录后浏览器发给 API 的那张凭证、OAuth 提供方交给接入应用的身份断言,也是大多数现代会话与访问控制流程所搭乘的”信封”。它的诱人之处在于:用户是谁、能做什么、令牌何时过期这些声明,都以 JSON 形式装在令牌本身里面,接收方无需查库就能读到。

一个 JWT 恰好由三段用点号分隔的 base64url 编码组成:header.payload.signature(头部.载荷.签名)。header 声明算法和令牌类型。payload 是一个装满声明的 JSON 对象——既有 sub(主体)、iat(签发时间)、exp(过期时间)、nbf(生效时间)这类标准声明,也有你应用自定义的任何声明。signature 是签发方用密钥或私钥对前两段计算出来的;校验它,才能证明令牌没被篡改。

本页解码并检视 JWT:把三段拆开、把 header 和 payload 的 base64url 解码成可读 JSON、把标准时间声明渲染成人类可读的日期,并实时显示状态徽章(Valid 有效 / Expired 已过期 / Not yet valid 尚未生效)。它刻意校验签名——那需要签发方的密钥或公钥,对一个 100% 客户端的工具来说超出了范围。签名段会原样显示,不做处理。

如何使用#

  1. 把令牌粘进左侧的输入框。它必须是三段以点号分隔的内容,前后空白会被自动 trim。
  2. 点击 Sample(示例)载入一个内置的示例令牌(带 iat/exp/nbf),只想看看结构时很方便。
  3. 点击 Clear(清空)清空输入和结果区。
  4. 读取右侧面板:
    • 顶部的状态徽章——根据 nbfexp 与当前时间的对比,显示绿色的 ValidExpiredNot yet valid
    • Header(头部)卡片(标题栏会显示算法,如 HS256)。
    • Payload(载荷)卡片,按 JSON 美化输出。
    • 时间声明列表——签发时间、生效时间、过期时间,同时给出 unix 时间戳和可读日期。
    • Signature(签名)段,原样显示,因为它仍是 base64url 编码的字节。
  5. 如果令牌格式有误,红色状态行会告诉你到底是在三段式形状校验、base64url 解码,还是 JSON 解析这一步失败的。

主要特性#

  • 实时时间声明状态。 读取 iatnbfexp,直接告诉你令牌当前是有效、已过期,还是尚未生效——这正是你排查登录故障时真正想问的三个问题。
  • 可读日期。 1700000000 这种 unix 时间戳会旁边附上它对应的 UTC 日期,省得你在脑子里换算纪元。
  • 算法一眼可见。 header 里的 alg 值被提到 Header 卡片的标题栏,你立刻能看到手里是 HS256RS256,还是某种意料之外的算法。
  • UTF-8 安全解码。 base64url 段先解码成字节、再走 TextDecoder,所以非 ASCII 声明(其他脚本的姓名、角色)能正确渲染,而不是一串乱码。
  • 只解码、永不校验。 本工具永远不会向你索要密钥,所以你可以放心粘贴不太信任的令牌:不会发送到任何地方,签名只显示不校验。

实战示例#

点击 Sample,输入框会填入一个令牌,其 header 解码后是:

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

payload 解码后是:

{
  "sub": "1234567890",
  "name": "ArpGate Demo",
  "iat": 1700000000,
  "exp": 4102444800,
  "nbf": 1699999000
}

时间声明列表会显示:

签发时间    1700000000  (2023-11-14 22:13:20 UTC)
生效时间    1699999000  (2023-11-14 21:56:40 UTC)
过期时间    4102444800  (2100-01-01 00:00:00 UTC)

状态徽章显示 Valid,因为当前时间在 nbf 之后、exp 之前。签名段则原样显示为字面字符串 c2FtcGxlLXNpZ25hdHVyZS1ub3QtdmVyaWZpZWQ——解码后是文本 “sample-signature-not-verified”,这是一个刻意留下的标记,说明本令牌的签名只是示例,并非真正的 HMAC-SHA256 输出。

最后这一点,是理解本工具时最关键的一件事:一个能干净解码的令牌,并不一定是一个可信的令牌。任何人都可以伪造 header 和 payload;只有签名——用签发方的密钥或公钥校验通过——才能证明其真实性。本页是用来读声明、排查时间窗口的;签名校验请务必放在你真正的后端去做。

常见问题#

这个工具能告诉我某个 JWT 是不是真的吗?#

不能,而且这是刻意为之。只解码只是读出令牌里的 JSON,并不能证明令牌确实由声称的签发方所发。要校验真实性,你需要与 alg 匹配的密钥(HS256 用共享密钥,RS256/ES256 用签发方公钥)以及一个运行在可信后端上的校验流程。千万不要把”解码干净”的令牌当成”已校验”的令牌。

状态显示 “Expired”(已过期),能在这里刷新令牌吗?#

不能。刷新意味着调用你认证服务器的刷新端点换取新的访问令牌——这是一个网络操作,本静态客户端页面无法、也不应该执行。你能在这里做的,是确认旧令牌确切在何时过期,而这通常正是你要找的线索。

iatnbfexp 有什么区别?#

iat(签发时间)是令牌被创建的时刻,属于信息性字段。nbf(生效时间)是令牌最早应被接受的时刻,早于 nbf 时,即使签名有效,校验方也应拒绝。exp(过期时间)是硬截止线,超过之后令牌必须被拒绝。一个规范的令牌应满足 nbf ≤ iat ≈ 当前时间,且 exp 在不远的将来(访问令牌通常几分钟,刷新令牌更长)。

我的 payload 里有非 ASCII 字符,在别处显示成乱码,为什么这里正常?#

因为有些解码器错误地把每个 base64url 字符当成一个字节,而不是先解码成原始字节再处理。本页先解码成 Uint8Array,再走 TextDecoder,把字节正确按 UTF-8 解释。这才是正确做法,也是为什么任何脚本的姓名、角色、权限范围都能原样显示。