package middleware import ( "net/http" "strings" "time" "anticaptcha/internal/config" "anticaptcha/internal/model" "github.com/gin-gonic/gin" "github.com/golang-jwt/jwt/v5" ) type Claims struct { UserID uint `json:"user_id"` Username string `json:"username"` Role string `json:"role"` jwt.RegisteredClaims } func JWTAuth() gin.HandlerFunc { return func(c *gin.Context) { authHeader := c.GetHeader("Authorization") if authHeader == "" { c.JSON(http.StatusUnauthorized, gin.H{"error": "未提供认证令牌"}) c.Abort() return } parts := strings.Split(authHeader, " ") if len(parts) != 2 || parts[0] != "Bearer" { c.JSON(http.StatusUnauthorized, gin.H{"error": "认证令牌格式错误"}) c.Abort() return } tokenString := parts[1] claims := &Claims{} token, err := jwt.ParseWithClaims(tokenString, claims, func(token *jwt.Token) (interface{}, error) { return []byte(config.Cfg.JWT.Secret), nil }) if err != nil || !token.Valid { c.JSON(http.StatusUnauthorized, gin.H{"error": "无效的认证令牌"}) c.Abort() return } // 将用户信息存入上下文 c.Set("user_id", claims.UserID) c.Set("username", claims.Username) c.Set("role", claims.Role) c.Next() } } func AdminOnly() gin.HandlerFunc { return func(c *gin.Context) { role, exists := c.Get("role") if !exists || role.(string) != "admin" { c.JSON(http.StatusForbidden, gin.H{"error": "权限不足"}) c.Abort() return } c.Next() } } func GenerateToken(userID uint, username string, role string) (string, error) { claims := Claims{ UserID: userID, Username: username, Role: role, RegisteredClaims: jwt.RegisteredClaims{ ExpiresAt: jwt.NewNumericDate(time.Now().Add(time.Duration(config.Cfg.JWT.ExpireTime) * time.Hour)), IssuedAt: jwt.NewNumericDate(time.Now()), }, } token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims) return token.SignedString([]byte(config.Cfg.JWT.Secret)) } func GetCurrentUserID(c *gin.Context) uint { if id, exists := c.Get("user_id"); exists { return id.(uint) } return 0 } func GetCurrentUser(c *gin.Context) (*model.User, error) { // 后续从数据库查询 return nil, nil }