什么是 JWT?
JWT(JSON Web Token,RFC 7519)是一种开放标准,用于在各方之间以 JSON 对象的形式安全地传输信息。JWT 通常用于身份认证和信息交换场景。
JWT 的结构
一个 JWT 由三部分组成,用点号(.)分隔:
Header.Payload.Signature
1. Header(头部)
Header 通常包含两部分信息:
- alg:签名算法,如
HS256、RS256、ES256 - typ:令牌类型,固定为
JWT
示例:
{"alg": "RS256", "typ": "JWT"}
2. Payload(载荷)
Payload 包含声明(Claims),即要传输的数据。声明分为三类:
-
注册声明(Registered Claims):预定义的标准字段
sub(Subject):主体,通常为用户 IDiss(Issuer):签发者exp(Expiration Time):过期时间iat(Issued At):签发时间aud(Audience):受众nbf(Not Before):生效时间
-
公共声明(Public Claims):自定义字段,需在 IANA 注册或使用命名空间避免冲突
-
私有声明(Private Claims):双方约定的自定义字段
3. Signature(签名)
签名用于验证消息在传输过程中未被篡改。对于 HS256 算法,签名计算公式为:
HMACSHA256(base64UrlEncode(header) + "." + base64UrlEncode(payload), secret)
重要安全提示
JWT 的 Payload 是 Base64 编码而非加密,内容是明文可读的! 切勿在 JWT 中存放密码、信用卡号等敏感信息。
签名算法选择
对称算法(HS256/HS384/HS512)
- 使用同一个密钥进行签名和验证
- 适合单一服务端应用
- 密钥必须严格保密
非对称算法(RS256/ES256)— 推荐
- 使用私钥签名,公钥验证
- 适合微服务/分布式系统
- 公钥可以安全分发
- 推荐 RS256 或 ES256
JWT 验证要点
必须验证的字段
- 签名验证:使用公钥或共享密钥验证签名
- exp(过期时间):拒绝过期的 token
- nbf(生效时间):拒绝尚未生效的 token
- iss(签发者):验证签发者是否可信
- aud(受众):验证 token 是否为本服务签发
常见安全风险
- alg=none 攻击:服务端必须拒绝
alg: "none"的 token - 密钥混淆攻击:验证算法必须与预期一致,防止 HS256 token 使用 RSA 公钥作为密钥
- Token 泄露:不要在 URL 参数中传递 JWT,使用
Authorization: Bearer <token>头部
Token 生命周期管理
推荐方案
- Access Token:有效期 15-60 分钟
- Refresh Token:有效期 7-30 天,支持轮换(Rotation)
- 使用 Redis 维护黑名单用于紧急吊销
- 短有效期 + Refresh Token 轮换是最佳实践
推荐 JWT 库
| 语言 | 推荐库 |
|---|---|
| Node.js | jsonwebtoken, jose |
| Python | PyJWT, python-jose |
| Java | jjwt, nimbus-jose-jwt |
| Go | golang-jwt/jwt, lestrrat-go/jwx |