JWT 的三段结构,以及过期时间怎么看
Header.Payload.Signature 三段分别是什么?为什么说 JWT 的 Payload 是明文、绝不能放敏感信息?过期时间字段 exp 又该按什么单位填?
JWT(JSON Web Token)长得像一个被两个点切成三段的乱码:
eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxIn0.dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk
三个部分分别是 Header、Payload、Signature,都是 Base64URL 编码。
Header:声明签名算法
解出来是一个小 JSON:
{ "alg": "HS256", "typ": "JWT" }
alg 指明签名算法。这里有个经典安全漏洞:早期实现如果不校验 alg,攻击者可以把它改成 none,从而伪造任意 token。服务端必须白名单式校验算法,不能信任 header 里的声明。
Payload:业务数据,但它是明文
这是最容易被误解的一段。Payload 只是 Base64URL 编码,不是加密——任何人拿到 token 都能解出来看。所以:
- 可以放:用户 ID、角色、过期时间、签发者
- 绝不能放:密码、身份证号、手机号、密钥
典型 Payload:
{ "sub": "1001", "role": "admin", "iat": 1790000000, "exp": 1790003600 }
关于时间字段有两个要点:
iat(签发时间)与exp(过期时间)都是秒级 Unix 时间戳,不是毫秒。填毫秒会让 token 立即过期或永不过期。exp是可选的,但强烈建议填。没有过期时间的 token 一旦泄露就是永久后门。
Signature:唯一防篡改的部分
签名是用 Header 里声明的算法,对「Base64(Header) + . + Base64(Payload)」加上服务端密钥计算出来的。
没有签名,前两段就是可以随便改的明文。 校验签名是 JWT 唯一的防伪机制,所以:
- HS256 的密钥必须足够长且保密(弱密钥可被离线爆破)
- RS256 用私钥签名、公钥验签,更适合多服务场景
- 校验时必须同时验签名和
exp
调试时怎么看
把 token 粘进 JWT 调试器,三段会分别解码展示,并标注过期时间与剩余有效期。
一个提醒:调试工具只是解码,不做签名校验。任何在线工具都不要粘贴生产环境的真实 token——Payload 是明文的,等于把用户信息交出去。