fix(gateway): 三处生产安全硬化(默认密钥/admin裸奔/CORS)

1) JWT 默认密钥:生产模式(APP_ENV=production|prod 或 GIN_MODE=release)下若未设
   JWT_SECRET 直接 log.Fatal,杜绝用开发默认值签发可伪造令牌;开发期警告并放行。
2) /admin 运维控制面(含模型 API 密钥管理)改挂 RequireAdmin:必须登录 +
   (设了 ADMIN_USER_IDS 则)uid 须在白名单;生产期未配置管理员直接 403。
3) CORS Allow-Origin 由 CORS_ALLOW_ORIGIN 配置(缺省 * 仅开发),非 * 时加 Vary。

build + auth 单测通过。仍属"小范围灰度"级,TLS/可观测/集成测试/HA 见 PROGRESS。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Blizzard
2026-06-18 12:55:04 +08:00
parent 9c19bb44f1
commit e05e6f5903
4 changed files with 82 additions and 6 deletions
+24 -2
View File
@@ -3,7 +3,9 @@ package auth
import (
"errors"
"log"
"os"
"strings"
"time"
"github.com/golang-jwt/jwt/v5"
@@ -13,8 +15,28 @@ import (
// TokenTTL 是访问令牌有效期。
const TokenTTL = 24 * time.Hour
// secret 是 JWT 签名密钥。生产经环境变量 JWT_SECRET 注入;缺省仅供开发(务必覆盖)。
var secret = []byte(envOr("JWT_SECRET", "sundynix-dev-secret-change-me"))
const devSecret = "sundynix-dev-secret-change-me"
// secret 是 JWT 签名密钥。生产必须经 JWT_SECRET 注入强密钥;
// 生产模式(APP_ENV=production/prod 或 GIN_MODE=release)下未设则直接 fatal,杜绝可伪造令牌。
var secret = []byte(resolveSecret())
func resolveSecret() string {
if s := os.Getenv("JWT_SECRET"); s != "" {
return s
}
if isProd() {
log.Fatal("[auth] 生产模式必须设置 JWT_SECRET(强随机密钥),拒绝使用开发默认值")
}
log.Println("[auth] ⚠️ 使用开发默认 JWT 密钥,生产务必设置 JWT_SECRET")
return devSecret
}
// isProd 判定是否生产环境。
func isProd() bool {
env := strings.ToLower(os.Getenv("APP_ENV"))
return env == "production" || env == "prod" || strings.ToLower(os.Getenv("GIN_MODE")) == "release"
}
// ErrInvalidToken 表示令牌无效/过期/签名不符。
var ErrInvalidToken = errors.New("invalid token")