JWT 是什么
JSON Web Token(RFC 7519)是一种紧凑的、自包含的令牌格式:把用户信息放进 JSON(Payload),用数字签名保证完整性(数据没被篡改)。核心优势:
- 无状态:服务端不存会话,天然支持分布式部署和水平扩展;
- 自包含:用户信息就在 token 里,验签通过即信任;
- 跨域友好:可在多服务/多域间传递。
组成:Header.Payload.Signature
header.payload.signature
- Header:算法和类型,如
{"alg":"HS256","typ":"JWT"}; - Payload:三类声明——注册声明(exp/iss/aud/sub)、公共声明、私有声明(如 user_id);
- Signature:对 header.payload 的签名。HS256 的计算:
HMACSHA256(base64Url(header) + "." + base64Url(payload), secret)
⚠️ Payload 只是 Base64 编码,不是加密——任何人都能解码看到内容,所以绝不能放密码等敏感信息。安全性来自签名(防篡改),不来自保密。
Go 实现(golang-jwt/jwt/v5)
go get github.com/golang-jwt/jwt/v5
生成 Token
type CustomClaims struct {
UserID int `json:"user_id"`
jwt.RegisteredClaims
}
func GenerateToken(userID int, secret string) (string, error) {
claims := CustomClaims{
UserID: userID,
RegisteredClaims: jwt.RegisteredClaims{
ExpiresAt: jwt.NewNumericDate(time.Now().Add(24 * time.Hour)),
Issuer: "myapp",
},
}
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
return token.SignedString([]byte(secret))
}
解析与验证

func ValidateToken(tokenString, secret string) (*CustomClaims, error) {
token, err := jwt.ParseWithClaims(tokenString, &CustomClaims{},
func(t *jwt.Token) (interface{}, error) {
// 关键:校验签名算法,防止算法混淆攻击(alg=none/RS256→HS256)
if _, ok := t.Method.(*jwt.SigningMethodHMAC); !ok {
return nil, fmt.Errorf("unexpected signing method: %v", t.Header["alg"])
}
return []byte(secret), nil
})
if err != nil { return nil, err }
claims, ok := token.Claims.(*CustomClaims)
if !ok || !token.Valid { return nil, errors.New("invalid token") }
return claims, nil
}
Gin 中间件集成
func JWTAuthMiddleware(secret string) gin.HandlerFunc {
return func(c *gin.Context) {
tokenString := c.GetHeader("Authorization")
if tokenString == "" {
c.AbortWithStatusJSON(401, gin.H{"error": "未提供Token"})
return
}
// 习惯上客户端带 "Bearer xxx",这里要剥掉前缀
tokenString = strings.TrimPrefix(tokenString, "Bearer ")
claims, err := ValidateToken(tokenString, secret)
if err != nil {
c.AbortWithStatusJSON(401, gin.H{"error": "无效Token"})
return
}
c.Set("user_id", claims.UserID)
c.Next()
}
}
安全实践
- 密钥:至少 256 位强随机密钥,放环境变量/密钥管理服务,绝不硬编码;定期轮换;
- 有效期:access token 设短(15min–24h),配合 Refresh Token 续期;
- 传输:必须 HTTPS;
- 主动失效:JWT 无法主动作废——登出/改密/封号需要黑名单(Redis 存 jti/version)或短过期策略;
- 校验 iss/aud:防止跨服务乱用 token;
- 算法白名单:验证时必须检查签名算法(见上面注释),防算法混淆攻击。
总结
JWT 用”签名保证完整 + 无状态换取扩展”,在微服务和分布式场景是标配。实现上关注三件事:密钥管理、有效期与刷新、主动失效机制。高安全场景可换 RS256(非对称,私钥签发、公钥验证,适合多服务共享验证)。


