JWT(JSON Web Token)的荷载(Payload)为什么不能放秘密(如密码、API密钥、银行卡号等)信息?
1. 荷载是Base64编码的,不是加密的
-
JWT 由三部分组成:
Header.Payload.Signature。- 示例jwt:eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHBpcmVkIjoxNzU2Mzg1NTAxLCJ1c2VyX2lkIjo0fQ.cmkkVxwzSubGNbkXqjY4ETIiKzX6a0wbiXVBiLl1b58
-
Payload 仅经过 Base64URL 编码,可以被任何人轻松解码(例如用 jwt.io 或简单的代码工具)。
# 解码Payload echo "eyJleHBpcmVkIjoxNzU2Mzg1NTAxLCJ1c2VyX2lkIjo0fQ" | base64 --decode输出:
{"expired":1756385501,"user_id":4} -
Base64 ≠ 加密!敏感信息会直接暴露。
2. JWT 的签名只保证完整性,不保证保密性
-
JWT 的签名(Signature)仅用于验证 Token 是否被篡改,无法阻止他人读取 Payload。
-
攻击者可以:
- 截获 Token → 解码 Payload → 直接获取敏感信息。
- 重放 Token(即使无法篡改,也能重复使用)。
3. JWT 可能被意外泄露
-
常见泄露场景:
- 浏览器缓存、日志文件、错误消息。
- HTTP 请求被中间人拦截(如未用 HTTPS)。
- 前端代码意外打印 Token(如
console.log(token))。
-
如果 Payload 含秘密信息,泄露后果更严重。
4. 违反安全最佳实践
- 最小权限原则:Payload 应仅包含必要信息(如用户ID、角色),而非全部数据。
- 秘密信息应存储在服务端:通过 Payload 中的用户ID 查询数据库获取敏感数据,而非直接放在 Token 中。
安全的使用方式
可以放在 Payload 中的数据:
- 用户公开信息(如用户ID、用户名、角色)。
- 业务无关数据(如 Token 签发时间
iat、过期时间exp)。
禁止放在 Payload 中的数据:
- 密码、API密钥、加密盐值。
- 银行卡号、身份证号、手机号(如需存储,应先加密)。
- 系统内部使用的敏感配置。
如何安全地传递敏感信息?
-
服务端存储:
- Payload 只放用户ID → 服务端通过ID查询数据库获取敏感信息。
-
加密 Payload(不推荐复杂化):
- 使用对称加密(如 AES)加密 Payload 字段,但增加维护成本。
-
短期 Token:
- 缩短 Token 有效期(如
exp: 15分钟),减少泄露风险。
- 缩短 Token 有效期(如