This commit is contained in:
toom1996
2026-08-30 10:45:34 +08:00
parent a6724265ad
commit 9c3403a903
23 changed files with 284 additions and 508 deletions

View File

@ -16,11 +16,12 @@ import (
// Config 应用总配置,结构与 configs/config.yml 一一对应。
type Config struct {
Server ServerConfig `yaml:"server"`
Database DatabaseConfig `yaml:"database"`
JWT JWTConfig `yaml:"jwt"`
Upload UploadConfig `yaml:"upload"`
CORS CORSConfig `yaml:"cors"`
Server ServerConfig `yaml:"server"`
Database DatabaseConfig `yaml:"database"`
JWT JWTConfig `yaml:"jwt"`
Upload UploadConfig `yaml:"upload"`
CORS CORSConfig `yaml:"cors"`
ClientSign ClientSignConfig `yaml:"client_sign"`
// loadedFrom 记录实际生效的配置文件绝对路径,仅用于启动日志。
// 小写不导出,yml 无法覆盖它。
@ -101,6 +102,25 @@ type CORSConfig struct {
MaxAge int `yaml:"max_age"`
}
// ClientSignConfig 公开接口「前端 JS 签名」配置。
//
// 给 /runway-looks(列表)与 /brands 两个批量查询接口加一层请求签名校验,
// 用于识别「请求大概率由前端 JS 构造」、抬高 casual 爬虫的批量抓取成本。
//
// 安全定位(务必知悉):
// - 这是「提高成本」而非「加密」——Secret 必须出现在前端 bundle 才能签名,对浏览器可见;
// 有决心的爬虫可反编译 JS 复刻签名逻辑。它用于拖慢 casual 爬虫,不能作为唯一防线。
// - 真正有效的组合是:本签名(识别大概率真前端)+ 按 IP 限流(兜住总量)。
// - Enabled=false 或 Secret 为空时中间件为 noop(不拦截),便于灰度与回滚。
type ClientSignConfig struct {
// Enabled 开关:false 时中间件不拦截,便于灰度上线与紧急回滚。
Enabled bool `yaml:"enabled"`
// Secret 签名密钥,必须与前端的 CLIENT_SIGN_SECRET 完全一致。生产经环境变量 CLIENT_SIGN_SECRET 注入随机长串。
Secret string `yaml:"secret"`
// TTLSeconds 签名时间戳容忍窗口(秒),用于防重放。默认 30。
TTLSeconds int `yaml:"ttl_seconds"`
}
// defaultConfig 返回内置默认值,保证 yml 缺字段时服务仍可启动。
func defaultConfig() *Config {
return &Config{
@ -117,7 +137,7 @@ func defaultConfig() *Config {
Port: "3306",
User: "root",
Password: "root",
Name: "db",
Name: "db_dev",
Charset: "utf8mb4",
LogLevel: "warn",
MaxIdleConns: 10,
@ -135,9 +155,14 @@ func defaultConfig() *Config {
CORS: CORSConfig{
AllowOrigins: []string{"*"},
AllowMethods: []string{"GET", "POST", "PUT", "DELETE", "OPTIONS"},
AllowHeaders: []string{"Content-Type", "Authorization", "X-Requested-With"},
AllowHeaders: []string{"Content-Type", "Authorization", "X-Requested-With", "X-Sign", "X-Sign-Ts", "X-Sign-Nonce"},
MaxAge: 86400,
},
ClientSign: ClientSignConfig{
Enabled: false,
Secret: "",
TTLSeconds: 30,
},
}
}
@ -214,6 +239,10 @@ func (c *Config) applyEnv() {
envStr("JWT_SECRET", &c.JWT.Secret)
envInt("JWT_EXPIRE_HOURS", &c.JWT.ExpireHours)
envBool("CLIENT_SIGN_ENABLED", &c.ClientSign.Enabled)
envStr("CLIENT_SIGN_SECRET", &c.ClientSign.Secret)
envInt("CLIENT_SIGN_TTL", &c.ClientSign.TTLSeconds)
envStr("UPLOAD_DIR", &c.Upload.Dir)
envStr("UPLOAD_URL_PREFIX", &c.Upload.URLPrefix)
}