package middleware import ( "errors" "strconv" "git.echol.cn/loser/st/server/global" "git.echol.cn/loser/st/server/model/app" "git.echol.cn/loser/st/server/model/common/response" "git.echol.cn/loser/st/server/utils" "github.com/gin-gonic/gin" "github.com/golang-jwt/jwt/v5" ) // AppJWTAuth 前台用户 JWT 认证中间件 func AppJWTAuth() gin.HandlerFunc { return func(c *gin.Context) { token := GetToken(c) if token == "" { response.FailWithDetailed(gin.H{"reload": true}, "未登录或非法访问", c) c.Abort() return } // 解析 JWT claims, err := utils.ParseAppToken(token) if err != nil { if errors.Is(err, jwt.ErrTokenExpired) { response.FailWithDetailed(gin.H{"reload": true}, "Token 已过期", c) } else { response.FailWithDetailed(gin.H{"reload": true}, "Token 无效", c) } c.Abort() return } // 验证用户类型(确保是前台用户) if claims.UserType != utils.UserTypeApp { response.FailWithMessage("无效的用户类型", c) c.Abort() return } // 查询用户是否存在 var user app.AppUser err = global.GVA_DB.Where("id = ?", claims.UserID).First(&user).Error if err != nil { response.FailWithMessage("用户不存在", c) c.Abort() return } // 检查用户状态 if !user.Enable { response.FailWithMessage("用户已被禁用", c) c.Abort() return } if user.Status != "active" { response.FailWithMessage("账户状态异常", c) c.Abort() return } // 将用户信息存入上下文 c.Set("appUserId", user.ID) c.Set("appUser", &user) c.Set("appUsername", user.Username) c.Next() } } // GetAppUserID 从上下文获取前台用户 ID(需要鉴权的接口使用) func GetAppUserID(c *gin.Context) uint { if userID, exists := c.Get("appUserId"); exists { return userID.(uint) } return 0 } // GetOptionalAppUserID 从上下文获取可选的前台用户 ID(公开接口使用) // 如果用户已登录,返回用户 ID;否则返回 nil func GetOptionalAppUserID(c *gin.Context) *uint { // 先尝试从上下文获取(通过鉴权中间件设置) if userID, exists := c.Get("appUserId"); exists { if id, ok := userID.(uint); ok { return &id } } // 如果上下文中没有,尝试手动解析 Token(用于公开接口) token := GetToken(c) if token == "" { return nil } claims, err := utils.ParseAppToken(token) if err != nil { return nil } if claims.UserType != utils.UserTypeApp { return nil } return &claims.UserID } // GetAppUser 从上下文获取前台用户信息 func GetAppUser(c *gin.Context) *app.AppUser { if user, exists := c.Get("appUser"); exists { return user.(*app.AppUser) } return nil } // GetAppUsername 从上下文获取前台用户名 func GetAppUsername(c *gin.Context) string { if username, exists := c.Get("appUsername"); exists { return username.(string) } return "" } // GetToken 从请求中获取 Token // 优先从 Header 获取,其次从 Query 参数获取 func GetToken(c *gin.Context) string { token := c.Request.Header.Get("x-token") if token == "" { token = c.Request.Header.Get("Authorization") if token != "" && len(token) > 7 && token[:7] == "Bearer " { token = token[7:] } } if token == "" { token = c.Query("token") } return token } // SetAppUserID 设置用户 ID 到上下文(用于某些特殊场景) func SetAppUserID(c *gin.Context, userID uint) { c.Set("appUserId", userID) c.Set("appUserIdStr", strconv.Itoa(int(userID))) }