JWT 鉴权机制详解
什么是 JWT
JWT(JSON Web Token)是一种开放标准(RFC 7519),它定义了一种紧凑的、自包含的方式,用于在各方之间以 JSON 对象的形式安全传输信息。
JWT 结构
JWT 由三部分组成,以点号分隔:
header.payload.signature
Header(头部)
{
"alg": "HS256",
"typ": "JWT"
}
Payload(负载)
包含声明(claims),分为三类:
- 注册声明:
iss(签发者)、sub(主题)、exp(过期时间)、iat(签发时间) - 公共声明:自定义字段,建议在 IANA 注册或使用命名空间避免冲突
- 私有声明:双方协商的自定义字段
{
"sub": "1234567890",
"name": "张三",
"iat": 1516239022,
"exp": 1516242622,
"role": "admin"
}
Signature(签名)
HMACSHA256(
base64UrlEncode(header) + "." + base64UrlEncode(payload),
secret
)
鉴权流程
1. 用户登录 → 服务器验证凭据 → 签发 JWT → 返回给客户端
2. 客户端存储 JWT(localStorage / Cookie)→ 每次请求在 Authorization 头携带
3. 服务器接收请求 → 验证 JWT 签名 → 解析 payload → 执行鉴权逻辑
使用示例(Go)
生成 JWT
import "github.com/golang-jwt/jwt/v5"
type Claims struct {
UserID string `json:"user_id"`
Role string `json:"role"`
jwt.RegisteredClaims
}
func GenerateToken(userID, role string) (string, error) {
claims := &Claims{
UserID: userID,
Role: role,
RegisteredClaims: jwt.RegisteredClaims{
ExpiresAt: jwt.NewNumericDate(time.Now().Add(24 * time.Hour)),
IssuedAt: jwt.NewNumericDate(time.Now()),
Issuer: "my-app",
},
}
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
return token.SignedString([]byte("your-secret-key"))
}
验证 JWT
func ValidateToken(tokenString string) (*Claims, error) {
token, err := jwt.ParseWithClaims(tokenString, &Claims{},
func(token *jwt.Token) (interface{}, error) {
if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"])
}
return []byte("your-secret-key"), nil
})
if err != nil {
return nil, err
}
claims, ok := token.Claims.(*Claims)
if !ok || !token.Valid {
return nil, fmt.Errorf("invalid token")
}
return claims, nil
}
安全注意事项
签名算法
- 使用强签名算法如 HS256 或 RS256
- 服务端验证时必须校验
alg头,防止算法混淆攻击
密钥管理
- HS256:密钥足够复杂,定期轮转
- RS256:私钥妥善保管,公钥分发到各服务
Token 存储
- 前端:优先使用 httpOnly Cookie(防 XSS),而非 localStorage
- 后端:永远不要存储明文的 JWT
Token 失效
JWT 签发后无法服务端主动撤销。解决方案:
- 短过期时间 + 刷新 Token:access token 15 分钟,refresh token 7 天
- 黑名单:使用 Redis 维护失效 Token 集合
- 版本号:用户密码变更时递增版本号,验证时对比
与 Session 的对比
| 特性 | JWT | Session |
|---|---|---|
| 存储方式 | 客户端 | 服务端内存/Redis |
| 扩展性 | 天然无状态,易水平扩展 | 需要共享存储 |
| 主动失效 | 复杂(需黑名单) | 直接删除 Session |
| 数据量 | Token 较大 | 仅 Session ID |
| 安全性 | 注意 XSS/CSRF | 相对成熟 |