面试官:JWT的荷载(Payload)为什么不能放秘密(如密码、API密钥、银行卡号等)信息?

107 阅读2分钟

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密钥、加密盐值。
  • 银行卡号、身份证号、手机号(如需存储,应先加密)。
  • 系统内部使用的敏感配置。

如何安全地传递敏感信息?

  1. 服务端存储

    • Payload 只放用户ID → 服务端通过ID查询数据库获取敏感信息。
  2. 加密 Payload(不推荐复杂化):

    • 使用对称加密(如 AES)加密 Payload 字段,但增加维护成本。
  3. 短期 Token

    • 缩短 Token 有效期(如 exp: 15分钟),减少泄露风险。