62 lines
1.9 KiB
Go
62 lines
1.9 KiB
Go
package config
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
)
|
|
|
|
// Config 服务器配置(环境变量优先,.env 兜底)
|
|
type Config struct {
|
|
ServerAddr string
|
|
MySQLDSN string
|
|
RedisAddr string
|
|
RedisPass string
|
|
JWTSecret string
|
|
BaseURL string
|
|
PublicBaseURL string // 浏览器侧访问地址(邀请链接等)
|
|
StorageDir string
|
|
StaticDir string // 前端生产构建目录(空=不托管静态)
|
|
MaxUploadBytes int64 // multipart 上传体积上限
|
|
}
|
|
|
|
// Load 从环境变量加载
|
|
func Load() *Config {
|
|
jwt := getenv("JWT_SECRET", "dev-secret-change-me")
|
|
if jwt == "dev-secret-change-me" || jwt == "please-change-me-in-production" || len(jwt) < 16 {
|
|
// 生产安全红线:默认/过短密钥可被伪造 JWT(含 admin 提权)。
|
|
// 保留 dev 默认值以便本地开发,但在任何环境都打印醒目告警。
|
|
println("!! [security] JWT_SECRET 使用默认值或长度不足(<16)。生产环境必须设置强随机 JWT_SECRET,否则任何人都能伪造令牌(admin 提权)。")
|
|
}
|
|
return &Config{
|
|
ServerAddr: getenv("SERVER_ADDR", ":8090"),
|
|
MySQLDSN: getenv("MYSQL_DSN", "root:everypublish@tcp(127.0.0.1:3306)/everypublish?charset=utf8mb4&parseTime=True&loc=Local"),
|
|
RedisAddr: getenv("REDIS_ADDR", "127.0.0.1:6379"),
|
|
RedisPass: getenv("REDIS_PASSWORD", ""),
|
|
JWTSecret: jwt,
|
|
BaseURL: getenv("BASE_URL", "http://127.0.0.1:8090"),
|
|
PublicBaseURL: getenv("PUBLIC_BASE_URL", getenv("BASE_URL", "http://127.0.0.1:8090")),
|
|
StorageDir: getenv("STORAGE_DIR", "./data/materials"),
|
|
StaticDir: getenv("STATIC_DIR", "../apps/web/dist"),
|
|
MaxUploadBytes: getenvInt64("MAX_UPLOAD_BYTES", 2<<30),
|
|
}
|
|
}
|
|
|
|
func getenvInt64(k string, def int64) int64 {
|
|
v := os.Getenv(k)
|
|
if v == "" {
|
|
return def
|
|
}
|
|
var n int64
|
|
if _, err := fmt.Sscanf(v, "%d", &n); err != nil || n <= 0 {
|
|
return def
|
|
}
|
|
return n
|
|
}
|
|
|
|
func getenv(k, def string) string {
|
|
if v := os.Getenv(k); v != "" {
|
|
return v
|
|
}
|
|
return def
|
|
}
|