JWT 是什么?token 里存了什么,为什么不能放隐私

一、三段结构:点号分开的三块

一个典型的 JWT 长这样(用点号分成三段):

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMDI0IiwibmFtZSI6IuW8oOS4iSIsInJvbGUiOiJ1c2VyIiwiaWF0IjoxNzg5MDAwMDAwLCJleHAiOjE3ODkwMDM2MDB9.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
内容编码后示例
第一段头部 headereyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
第二段载荷 payloadeyJzdWIiOiIxMDI0IiwibmFtZSI6IuW8oOS4iSIs…
第三段签名 signatureSflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

解码前两段(Base64URL 解码)就能看到明文内容:

{"alg":"HS256","typ":"JWT"}
{"sub":"1024","name":"张三","role":"user","iat":1789000000,"exp":1789003600}

这是理解 JWT 的关键:前两段不是加密,只是「换个写法」。 任何人拿到 token 都能解出里面的字段——包括中间人、日志系统、以及任何一个在线解码工具。

二、所以:token 里不要放敏感信息

可以放不要放
用户 ID、角色、租户标识手机号、身份证号、银行卡号
权限范围(scope)、令牌版本密码、密码哈希、密钥
过期时间、签发时间任何「泄露就有损失」的个人信息

JWT 只保证完整性(内容没被改过,前提是验签正确),不保证保密性。要保密必须加密(JWE 或服务端 session)。

三、三个时间字段:iat / nbf / exp

三者都是 epoch 秒(10 位整数,不是毫秒):

字段含义说明
iat签发时间用于审计、判断令牌新鲜度
nbf生效时间早于它服务端应拒绝(可选)
exp过期时间到点失效,是最常用的字段

上面那个例子里 exp 是 1789003600,解码工具会直接标出「已过期」——因为它已经早于当前时间。

两个细节:

  • exp 是令牌自己声明的,服务端如果压根不校验,过期的 token 照样能用。看到「已过期」应按失效处理,但不能假定「没过期就一定安全」;
  • 时钟偏差会造成误判:客户端与服务端时间差几分钟,就可能让刚签发的 token 被判成未生效。工程上一般留 30~60 秒容差。

四、为什么不验签

验签需要密钥或公钥:HMAC 算法要对密钥、RSA/ECDSA 要对公钥。把这些放到网页前端等于直接公开,任何人都能自己签发任意内容的 token。所以在线工具只解结构、不冒充校验:

  • 能判断:格式是否合法、三段能否解码、时间字段状态、alg 是什么;
  • 不能判断:令牌是否真实、是否被篡改、签发方是谁。

验签永远在服务端做,而且要显式指定允许的算法列表——不校验 alg 就可能被「算法混淆」攻击(把 HS256 换成 none 或反之)。

五、三个常见误解

  1. 「Base64 是加密」:不是。Base64 与 Base58、Base32 一样只是编码,用来换一种字符写法,没有密钥、一键还原;
  2. 「签名能防别人看内容」:不能。签名只防篡改,内容依然是明文;
  3. 「token 越长越安全」:长度只和载荷大小有关,安全性取决于签名算法强度、密钥长度与服务端校验是否到位。

还有一个常见发现:如果第三段是空的(token 以点号结尾),说明这是个 alg: none 的未签名令牌——生产环境出现它意味着鉴权形同虚设

六、直接算

JWT 解析器:本地解码三段结构,标出 exp/iat/nbf 状态与 alg

Base58 编解码:另一种「换写法不加密」的编码,好抄写但不保密

编码转换:Base64、URL 编码、Unicode 转义的互转

本站文章为个人使用经验的原创整理,除已注明来源的引用外均为本人撰写。文中涉及的软件名称、商标、截图等归各自权利人所有,引用仅用于说明与交流。如认为本站内容侵犯了你的合法权益,请通过「关于本站」页面的联系方式告知,核实后将及时更正或删除。