package middleware import ( "bytes" "encoding/json" "fmt" "io" "net/http" "strings" "time" "github.com/gin-gonic/gin" "infogenie-backend/config" ) type AuthCenterUser struct { Account string `json:"account"` Username string `json:"username"` Email string `json:"email"` Level int `json:"level"` SproutCoins float64 `json:"sproutCoins"` AvatarURL string `json:"avatarUrl"` WebsiteURL string `json:"websiteUrl"` Bio string `json:"bio"` CheckInDays int `json:"checkInDays"` CheckInStreak int `json:"checkInStreak"` } type VerifyResponse struct { Valid bool `json:"valid"` User *AuthCenterUser `json:"user,omitempty"` Error string `json:"error,omitempty"` BanReason string `json:"banReason,omitempty"` } func verifyTokenWithAuthCenter(tokenStr string) (*VerifyResponse, error) { body, _ := json.Marshal(map[string]string{"token": tokenStr}) url := config.Cfg.AuthCenter.APIURL + "/api/auth/verify" req, err := http.NewRequest("POST", url, bytes.NewReader(body)) if err != nil { return nil, fmt.Errorf("创建请求失败: %w", err) } req.Header.Set("Content-Type", "application/json") req.Header.Set("X-Auth-Client", "infogenie") req.Header.Set("X-Auth-Client-Name", "万象口袋") client := &http.Client{Timeout: 10 * time.Second} resp, err := client.Do(req) if err != nil { return nil, fmt.Errorf("请求认证中心失败: %w", err) } defer resp.Body.Close() data, _ := io.ReadAll(resp.Body) if resp.StatusCode == 401 { return &VerifyResponse{Valid: false, Error: "invalid token"}, nil } var result VerifyResponse if err := json.Unmarshal(data, &result); err != nil { return nil, fmt.Errorf("解析认证响应失败: %w", err) } return &result, nil } func extractToken(c *gin.Context) string { auth := c.GetHeader("Authorization") if strings.HasPrefix(auth, "Bearer ") { return auth[7:] } return auth } func JWTAuth() gin.HandlerFunc { return func(c *gin.Context) { tokenStr := extractToken(c) if tokenStr == "" { c.JSON(http.StatusUnauthorized, gin.H{"success": false, "message": "缺少认证token"}) c.Abort() return } result, err := verifyTokenWithAuthCenter(tokenStr) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"success": false, "message": "认证服务暂时不可用"}) c.Abort() return } if !result.Valid || result.User == nil { msg := "Token无效或已过期" if result.BanReason != "" { msg = "账户已被封禁" } c.JSON(http.StatusUnauthorized, gin.H{"success": false, "message": msg}) c.Abort() return } c.Set("account", result.User.Account) c.Set("username", result.User.Username) c.Set("email", result.User.Email) c.Set("sprout_coins", result.User.SproutCoins) c.Set("auth_user", result.User) c.Next() } } func OptionalJWTAuth() gin.HandlerFunc { return func(c *gin.Context) { tokenStr := extractToken(c) if tokenStr != "" { result, err := verifyTokenWithAuthCenter(tokenStr) if err == nil && result.Valid && result.User != nil { c.Set("account", result.User.Account) c.Set("username", result.User.Username) c.Set("email", result.User.Email) c.Set("sprout_coins", result.User.SproutCoins) c.Set("auth_user", result.User) } } c.Next() } }