package config import ( "crypto/rand" "encoding/base64" "log" "os" "strings" "github.com/joho/godotenv" ) // Config 应用配置 // Logan.Li type Config struct { // 服务器配置 Port string Mode string // debug, release // 数据库配置 DBDriver string DBHost string DBPort string DBUser string DBPassword string DBName string // JWT 配置 JWTSecret string // CORS 配置 CORSOrigins []string } // Load 从环境变量加载配置 // Logan.Li func Load() *Config { // 加载 .env 文件(如果存在) // Logan.Li _ = godotenv.Load() cfg := &Config{ Port: getEnv("PORT", "9001"), Mode: getEnv("GIN_MODE", "debug"), DBDriver: getEnv("DB_DRIVER", "sqlite"), DBHost: getEnv("DB_HOST", "127.0.0.1"), DBPort: getEnv("DB_PORT", "3306"), DBUser: getEnv("DB_USER", "root"), DBPassword: getEnv("DB_PASSWORD", ""), DBName: getEnv("DB_NAME", "db.sqlite3"), JWTSecret: getEnv("JWT_SECRET", ""), CORSOrigins: []string{ "http://localhost:5181", "http://127.0.0.1:5181", "http://localhost:3000", "http://127.0.0.1:3000", }, } // 安全检查:生产环境拒绝空密钥,开发环境使用进程级随机密钥避免固定后门。 // Logan.Li if cfg.JWTSecret == "" { if cfg.Mode == "release" { log.Fatal("[安全] 生产环境必须设置 JWT_SECRET 环境变量") } cfg.JWTSecret = generateEphemeralJWTSecret() log.Println("[安全] JWT_SECRET 未设置,已生成仅当前开发进程有效的随机密钥") } return cfg } // IsOriginAllowed 判断浏览器 Origin 是否在显式 CORS 白名单中。 // Logan.Li func (c *Config) IsOriginAllowed(origin string) bool { for _, allowed := range c.CORSOrigins { if strings.EqualFold(strings.TrimSpace(origin), strings.TrimSpace(allowed)) { return true } } return false } // generateEphemeralJWTSecret 生成开发环境临时 JWT 密钥。 // Logan.Li func generateEphemeralJWTSecret() string { bytes := make([]byte, 32) if _, err := rand.Read(bytes); err != nil { log.Fatal("[安全] 生成开发 JWT 密钥失败") } return base64.RawURLEncoding.EncodeToString(bytes) } // getEnv 读取环境变量,不存在则返回默认值 // Logan.Li func getEnv(key, defaultValue string) string { if value := os.Getenv(key); value != "" { return value } return defaultValue }