JWT 生成实战,从 header、payload 到 HS256 签名一次写清
手把手讲 JWT 的三段结构、HS256 对称签名怎么算、sub 和 exp 这些常见 claims 怎么填,以及调试接口时怎么用一个测试 token 省掉整套登录流程,附密钥安全注意点。
JWT 生成实战,从 header、payload 到 HS256 签名一次写清
调接口时,我最常卡在鉴权这一步。后端要 token,可登录服务还没起来,或者我只想验证某个边界条件。这时候自己手动签一个 JWT,往往比把整套 OAuth 流程跑通快得多。这篇把生成一个 JWT 的全过程拆开讲,你看完就能自己造 token。
JWT 到底是三段什么
一个 JWT 长这样:header.payload.signature,三段用点号隔开。前两段是 base64url 编码的 JSON,第三段是签名。
header 描述算法和类型,通常就两个字段:
{"alg":"HS256","typ":"JWT"}
payload 装的是声明(claims),也就是你想传的数据。RFC 7519 定义了一批注册声明,常用的有 sub(主体,一般是用户 ID)、iat(签发时间)、exp(过期时间)。这三个时间相关的字段都是 Unix 秒级时间戳,不是毫秒。
signature 是把前两段拼起来,用密钥算 HMAC 得到的。这一段保证 header 和 payload 没被人动过。
HS256 对称签名是怎么算出来的
HS256 全称 HMAC-SHA256,属于对称签名,签名和验证用同一把密钥。计算过程就一句话:
HMACSHA256(base64url(header) + "." + base64url(payload), secret)
先把 header 和 payload 各自 base64url 编码,中间用点号连起来,再拿这个字符串和你的 secret 做一次 HMAC-SHA256,输出再 base64url 编码,就是第三段。
关键性质是确定性:同样的 header、payload 和 secret,算出来的签名一定一模一样。所以两个人签同一份数据却得到不同 token,问题一定出在这三者之一。我见过最多的坑是 secret 末尾多了个换行,或者 JSON 里留了空格没压缩(规范做法是签名前先 minify)。
跑一个真实例子
假设我要给用户 42 造一个管理员 token,payload 这样写:
{"sub":"42","role":"admin","iat":1735689600,"exp":1735693200}
配上 header {"alg":"HS256","typ":"JWT"} 和密钥 dev-only-secret,签出来的结构大致是:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI0MiIsInJvbGUiOiJhZG1pbiIsImlhdCI6MTczNTY4OTYwMCwiZXhwIjoxNzM1NjkzMjAwfQ.<signature>
第一段解出来就是 header,第二段就是上面那串 payload,第三段是 HMAC 结果。你可以把它直接塞进 curl -H "Authorization: Bearer ...",30 秒内就跑通了后端真实的鉴权中间件,完全不用先登录。签好之后想反向核对一下,扔进 JWT 解码器 看看每段解出来对不对就行。
调试和测试里它最有用
第一人称说一句,这个工具在我手里最高频的用法不是「正经发 token」,而是造各种边界 token 来逼出 bug。想测 401 处理,就把 exp 设成 1577836800(2020 年 1 月)签一个已经过期的 token,扔给接口,正确的服务端该返回 401 并触发刷新,要是返回 200,说明过期校验根本没生效。想给新人演示 HMAC 防篡改,就先用 role:"user" 签一个,再把 secret 改一个字符重签,签名整段都变,直观说明攻击者拿不到 secret 就造不出有效 token。
密钥安全这块别马虎
HS256 安全不安全,几乎全看 secret。RFC 7518 要求密钥长度不短于哈希输出:HS256 至少 32 字节、HS384 至少 48 字节、HS512 至少 64 字节。请用 openssl rand -base64 32 这种随机密钥,别拿人类口令凑数,短而可猜的 secret 等于没签。
还有两条铁律。一是别拿生产密钥来「随便试试」,任何你输入或粘贴的 secret 都会留在剪贴板和 shell 历史里,等于已经暴露,测试就用 test-secret-123 这种一次性密钥。二是对外开放、客户端各自一把钥匙的场景,别用对称的 HS 系列,改用非对称的 RS256 或 ES256,验证方只拿公钥,不必共享签名密钥。
如果你只是想确认密钥本身的哈希指纹,或者比对两段数据的摘要,可以顺手用 MD5 / SHA 哈希工具 算一下,跟签名调试是一对常用搭档。
Made by Toolora · Updated 2026-06-13