package middleware import ( "net/http" "strings" "github.com/gin-gonic/gin" "gorm.io/gorm" rediscache "wx_service/internal/common/redis/cache" "wx_service/internal/model" ) const ContextCurrentUserKey = "currentUser" func AuthMiddleware(db *gorm.DB, sessionCache *rediscache.SessionUserCache) gin.HandlerFunc { // AuthMiddleware 是一个 Gin 中间件: // - 从 Authorization: Bearer 里取 token // - 用 token(这里是 session_key)查用户 // - (可选) 优先从 Redis 缓存读取,减少每次都访问数据库 // - 查到后放进 gin.Context,供后面的 handler 使用 return func(c *gin.Context) { token := extractToken(c.GetHeader("Authorization")) if token == "" { c.AbortWithStatusJSON(http.StatusUnauthorized, model.Error(http.StatusUnauthorized, "missing authorization header")) return } if sessionCache != nil { if cachedUser, ok, err := sessionCache.Get(c.Request.Context(), token); err == nil && ok && cachedUser != nil { c.Set(ContextCurrentUserKey, cachedUser) c.Next() return } } var user model.User if err := db.WithContext(c.Request.Context()).Where("session_key = ?", token).First(&user).Error; err != nil { if err == gorm.ErrRecordNotFound { c.AbortWithStatusJSON(http.StatusUnauthorized, model.Error(http.StatusUnauthorized, "invalid token")) return } c.AbortWithStatusJSON(http.StatusInternalServerError, model.Error(http.StatusInternalServerError, "load user failed")) return } if sessionCache != nil { _ = sessionCache.Set(c.Request.Context(), token, &user) } c.Set(ContextCurrentUserKey, &user) c.Next() } } func extractToken(authHeader string) string { // 常见格式:Authorization: Bearer if authHeader == "" { return "" } parts := strings.SplitN(authHeader, " ", 2) if len(parts) != 2 { return "" } if !strings.EqualFold(parts[0], "Bearer") { return "" } return strings.TrimSpace(parts[1]) }