跨域
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 7m59s

This commit is contained in:
2026-05-07 16:28:23 +08:00
parent 573e887ca5
commit 73a3a04204
18 changed files with 634 additions and 894 deletions

View File

@@ -96,6 +96,7 @@ type LogRotationConfig struct {
type MiddlewareConfig struct {
EnableRateLimiter bool `mapstructure:"enable_rate_limiter"` // 启用限流器默认false
RateLimiter RateLimiterConfig `mapstructure:"rate_limiter"` // 限流器配置
CORS CORSConfig `mapstructure:"cors"` // 跨域配置
}
// ClientConfig 客户端行为开关配置
@@ -110,6 +111,17 @@ type RateLimiterConfig struct {
Storage string `mapstructure:"storage"` // "memory" 或 "redis"
}
// CORSConfig 跨域资源共享配置
type CORSConfig struct {
Enabled bool `mapstructure:"enabled"` // 是否启用 CORS
AllowOrigins string `mapstructure:"allow_origins"` // 允许的来源,多个来源用逗号分隔
AllowMethods string `mapstructure:"allow_methods"` // 允许的 HTTP 方法,多个方法用逗号分隔
AllowHeaders string `mapstructure:"allow_headers"` // 允许的请求头,多个请求头用逗号分隔
ExposeHeaders string `mapstructure:"expose_headers"` // 暴露给浏览器读取的响应头,多个响应头用逗号分隔
AllowCredentials bool `mapstructure:"allow_credentials"` // 是否允许携带凭证
MaxAge int `mapstructure:"max_age"` // 预检结果缓存秒数
}
// SMSConfig 短信服务配置
type SMSConfig struct {
GatewayURL string `mapstructure:"gateway_url"` // 短信网关地址
@@ -282,6 +294,20 @@ func (c *Config) Validate() error {
if c.Middleware.RateLimiter.Storage != "" && !validStorage[c.Middleware.RateLimiter.Storage] {
return fmt.Errorf("invalid configuration: middleware.rate_limiter.storage: invalid storage type (current value: %s, expected: memory or redis)", c.Middleware.RateLimiter.Storage)
}
if c.Middleware.CORS.Enabled {
if strings.TrimSpace(c.Middleware.CORS.AllowOrigins) == "" {
return fmt.Errorf("invalid configuration: middleware.cors.allow_origins: must be non-empty when CORS is enabled")
}
if c.Middleware.CORS.AllowCredentials && strings.TrimSpace(c.Middleware.CORS.AllowOrigins) == "*" {
return fmt.Errorf("invalid configuration: middleware.cors.allow_origins: wildcard origin is not allowed when allow_credentials is true")
}
if strings.TrimSpace(c.Middleware.CORS.AllowMethods) == "" {
return fmt.Errorf("invalid configuration: middleware.cors.allow_methods: must be non-empty when CORS is enabled")
}
if c.Middleware.CORS.MaxAge < 0 {
return fmt.Errorf("invalid configuration: middleware.cors.max_age: must be greater than or equal to 0")
}
}
// 短信服务验证(可选,配置 GatewayURL 时才验证其他字段)
if c.SMS.GatewayURL != "" {

View File

@@ -90,6 +90,14 @@ middleware:
max: 100
expiration: "1m"
storage: "memory"
cors:
enabled: true
allow_origins: "*"
allow_methods: "GET,POST,PUT,PATCH,DELETE,OPTIONS"
allow_headers: "Origin,Content-Type,Accept,Authorization,X-Requested-With,X-Request-ID"
expose_headers: "Content-Length,X-Request-ID"
allow_credentials: false
max_age: 86400
# 客户端配置
client:

View File

@@ -106,6 +106,13 @@ func bindEnvVariables(v *viper.Viper) {
"middleware.rate_limiter.max",
"middleware.rate_limiter.expiration",
"middleware.rate_limiter.storage",
"middleware.cors.enabled",
"middleware.cors.allow_origins",
"middleware.cors.allow_methods",
"middleware.cors.allow_headers",
"middleware.cors.expose_headers",
"middleware.cors.allow_credentials",
"middleware.cors.max_age",
"sms.gateway_url",
"sms.username",
"sms.password",
@@ -118,6 +125,9 @@ func bindEnvVariables(v *viper.Viper) {
"gateway.app_id",
"gateway.app_secret",
"gateway.timeout",
"polling.verbose_log",
"polling_auto_trigger.enable_auto_trigger",
"polling_auto_trigger.auto_trigger_system_user_id",
"worker.role",
"worker.instance_name",
"wechat.official_account.app_id",

View File

@@ -223,6 +223,10 @@ type AuthConfig struct {
// 所有错误统一返回 AppError由全局 ErrorHandler 处理
func Auth(config AuthConfig) fiber.Handler {
return func(c *fiber.Ctx) error {
if c.Method() == fiber.MethodOptions {
return c.SendStatus(fiber.StatusNoContent)
}
// 检查是否跳过认证
path := c.Path()
for _, skipPath := range config.SkipPaths {