package middleware import ( "errors" "net/http" "strings" "github.com/gin-gonic/gin" "github.com/user-management-system/internal/config" ) var corsConfig = config.CORSConfig{ AllowedOrigins: []string{}, // 默认为空,必须显式配置 AllowCredentials: false, // 默认关闭凭证,必须显式启用 } func validateCORSConfig(cfg config.CORSConfig) error { for _, origin := range cfg.AllowedOrigins { if origin == "*" && cfg.AllowCredentials { return errors.New("CORS 配置错误: AllowedOrigins 包含 '*' 时不能启用 AllowCredentials") } } return nil } func SetCORSConfig(cfg config.CORSConfig) error { if err := validateCORSConfig(cfg); err != nil { return err } corsConfig = cfg return nil } func CORS() gin.HandlerFunc { return func(c *gin.Context) { cfg := corsConfig origin := c.GetHeader("Origin") if origin != "" { allowOrigin, allowed := resolveAllowedOrigin(origin, cfg.AllowedOrigins, cfg.AllowCredentials) if !allowed { if c.Request.Method == http.MethodOptions { c.AbortWithStatus(http.StatusForbidden) return } c.AbortWithStatus(http.StatusForbidden) return } c.Writer.Header().Set("Access-Control-Allow-Origin", allowOrigin) if cfg.AllowCredentials { c.Writer.Header().Set("Access-Control-Allow-Credentials", "true") } } if c.Request.Method == http.MethodOptions { c.Writer.Header().Set("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS") c.Writer.Header().Set("Access-Control-Allow-Headers", "Authorization, Content-Type, X-Requested-With, X-CSRF-Token") c.Writer.Header().Set("Access-Control-Max-Age", "3600") c.AbortWithStatus(http.StatusNoContent) return } c.Next() } } func resolveAllowedOrigin(origin string, allowedOrigins []string, allowCredentials bool) (string, bool) { for _, allowed := range allowedOrigins { if allowed == "*" { if allowCredentials { return origin, true } return "*", true } if strings.EqualFold(origin, allowed) { return origin, true } } return "", false }