package middleware import ( "ego/internal/serializer" "ego/internal/util" "ego/pkg/logger" "net/http" "strings" "github.com/gin-gonic/gin" "go.uber.org/zap" ) // AuthRequired 验证 JWT 的中间件 func AuthRequired() gin.HandlerFunc { return func(c *gin.Context) { // 获取Authorization头 authHeader := c.GetHeader("Authorization") if authHeader == "" { sendUnauthorized(c, "缺少认证头") return } // 检查Bearer前缀 if !strings.HasPrefix(authHeader, "Bearer ") { sendUnauthorized(c, "无效的认证格式,请使用Bearer Token") return } // 提取token tokenString := strings.TrimPrefix(authHeader, "Bearer ") if tokenString == "" { sendUnauthorized(c, "Token不能为空") return } // 验证token claims, err := util.ValidateToken(tokenString) if err != nil { logger.Error(c, "Token验证失败", zap.Error(err)) sendUnauthorized(c, "Token验证失败: "+err.Error()) return } // 检查Redis中的token状态 redisKey := util.TokenGroup + claims.Username val, err := util.Get(c, redisKey) if err != nil { logger.Error(c, "Redis验证失败", zap.Error(err), zap.String("redisKey", redisKey)) sendUnauthorized(c, "登录状态验证失败") return } if val == "" { logger.Warn(c, "Token已过期或已注销", zap.String("username", claims.Username)) sendUnauthorized(c, "登录状态已过期,请重新登录") return } // 验证Redis中的token是否与当前token一致 if val != tokenString { logger.Warn(c, "Token不匹配,可能存在重复登录", zap.String("username", claims.Username)) sendUnauthorized(c, "登录状态异常,请重新登录") return } // 将用户信息存储到context中 c.Set("userID", claims.ID) c.Set("username", claims.Username) c.Set("id", claims.ID) // 保持向后兼容 logger.Debug(c, "JWT认证成功", zap.String("userID", claims.ID), zap.String("username", claims.Username)) c.Next() } } // sendUnauthorized 发送401未授权响应 func sendUnauthorized(c *gin.Context, message string) { c.AbortWithStatusJSON(http.StatusUnauthorized, serializer.Response{ Code: http.StatusUnauthorized, Msg: message, Data: nil, }) }