JWT 调试指南:exp 过期、签名失败、Base64 解不开

JWT 调试的三个高频问题:过期时间、签名校验失败、Base64URL 解不开。本文讲清各报错的真实含义与排查顺序,以及在浏览器本地安全查看令牌内容的方法。

先看清 JWT 的结构

一个 JWT 是三段用 . 分隔的 Base64URL 文本:头部.载荷.签名。前两段是 Base64URL 编码的 JSON,可以直接解出来读;签名段是服务端用密钥算出来的校验值,客户端改不了也解不开。

所以调试 JWT 时,第一步永远是先解前两段看内容,很多时候问题在解码阶段就能定位。

问题一:exp 提示过期

exp(expiration time)是过期时间戳,单位是秒,不是毫秒。常见误判:

问题二:signature 校验失败

签名算法和密钥不匹配,或令牌内容被改动过。排查顺序:

  1. 先确认头部声明的算法(alg)与服务端一致。历史上有「算法混淆」攻击:把 alg 改成 none 或 HS256 冒充 RS256,服务端若未固定校验算法就会误信任。
  2. 确认载荷没被改动。载荷虽然可见,但任何一位改动都会让签名对不上。
  3. 用相同算法和密钥重新计算签名做对比——DevKit 的 HMAC 签名工具可以直接验证 HS256 场景。

注意:HS256 用对称密钥(同一个密钥签名和验证),RS256 用私钥签名、公钥验证,两者的密钥不是一回事。

问题三:Base64 解不开

几乎都是变体用错。JWT 用的是 Base64URL:+→-、/→_、去掉末尾 =。用标准 Base64 解就会失败或得到乱码。DevKit 的 JWT 解析工具会自动处理这个差异。

安全提醒

JWT 的载荷是签名而非加密,任何拿到令牌的人都能解出里面的内容。所以不要在载荷里放密码、身份证号等敏感信息。需要保密应改用 JWE 或直接传输加密数据。

本地调试时可以直接把令牌粘进 DevKit 的 JWT 解析工具——它在浏览器内完成计算,令牌不会上传服务器,适合排查生产环境的真实令牌。

常见问题

JWT 可以解码吗?
前两段(头部、载荷)用 Base64URL 编码,可以直接解码查看内容。签名段是用密钥计算的校验值,无法解码还原。
JWT 载荷能放敏感信息吗?
不建议。载荷只是编码不是加密,任何拿到令牌的人都能解出内容。敏感信息应放服务端,前端只保留必要的标识类字段。
exp 用毫秒还是秒?
用秒。JWT 规范中 exp 是 NumericDate,单位为秒。如果你的系统里存的是毫秒时间戳,比较前需要除以 1000。