开源前加固认证与部署契约:加密随机 JWT、改密事务吊销、登录 CSRF,并禁止生产回落 localhost。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-09-23 02:07:34 +08:00
parent 6f054a903c
commit 3b550f2124
24 changed files with 372 additions and 355 deletions

View File

@@ -114,14 +114,61 @@ func TestAllowOriginDevAndProd(t *testing.T) {
}
}
const testJWTSecret = "unit-test-jwt-secret-32chars-min!!" // 满足 ≥32,非生产用
func TestIsWeakJWTSecret(t *testing.T) {
if !isWeakJWTSecret("") || !isWeakJWTSecret("short") {
t.Fatal("空/过短应判弱")
}
if !isWeakJWTSecret("abcdefghijklmnopqrstuvwxyzABCDEF") {
t.Fatal("旧确定性密钥应判弱")
}
if !isWeakJWTSecret("change-me") {
t.Fatal("占位值应判弱")
}
if isWeakJWTSecret(testJWTSecret) {
t.Fatal("测试强密钥不应判弱")
}
}
func TestGenerateSecretNotDeterministic(t *testing.T) {
a, err := generateSecret(32)
if err != nil {
t.Fatal(err)
}
b, err := generateSecret(32)
if err != nil {
t.Fatal(err)
}
if a == b {
t.Fatal("连续两次生成不应相同")
}
if isWeakJWTSecret(a) {
t.Fatalf("生成结果被误判为弱: %q", a)
}
}
func TestParseRejectsWeakExplicitSecret(t *testing.T) {
work := t.TempDir()
if err := os.WriteFile(filepath.Join(work, "app.ini"), []byte("[security]\nJWT_SECRET = change-me\n"), 0600); err != nil {
t.Fatal(err)
}
t.Setenv("JIANG13_WORK_PATH", work)
t.Setenv("JWT_SECRET", "")
if _, err := Parse(); err == nil {
t.Fatal("显式弱密钥应拒绝启动")
}
}
func TestParseSettingsMasterKeyFromIni(t *testing.T) {
work := t.TempDir()
key := "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQE="
if err := os.WriteFile(filepath.Join(work, "app.ini"), []byte("[security]\nJWT_SECRET = test-secret-not-for-prod\nSETTINGS_MASTER_KEY = "+key+"\n"), 0600); err != nil {
if err := os.WriteFile(filepath.Join(work, "app.ini"), []byte("[security]\nJWT_SECRET = "+testJWTSecret+"\nSETTINGS_MASTER_KEY = "+key+"\n"), 0600); err != nil {
t.Fatal(err)
}
t.Setenv("JIANG13_WORK_PATH", work)
t.Setenv("SETTINGS_MASTER_KEY", "")
t.Setenv("JWT_SECRET", "")
cfg, err := Parse()
if err != nil {
t.Fatal(err)
@@ -149,7 +196,7 @@ func TestParseSiteURLAndDataDir(t *testing.T) {
t.Setenv("SITE_URL", "https://bbs.example.com/")
t.Setenv("CORS_ORIGINS", " https://a.example.com ,https://b.example.com/ ")
t.Setenv("DATA_DIR", data)
t.Setenv("JWT_SECRET", "test-secret-not-for-prod")
t.Setenv("JWT_SECRET", testJWTSecret)
cfg, err := Parse()
if err != nil {
@@ -210,7 +257,7 @@ func TestEnsureAppIniBackfillsMissingKeys(t *testing.T) {
func TestParseSiteURLFromIni(t *testing.T) {
work := t.TempDir()
body := "[security]\nJWT_SECRET = test-secret-not-for-prod\n\n[app]\nDEV_MODE = true\nSITE_URL = https://forum.example.com/\nCORS_ORIGINS = https://a.example.com, https://b.example.com/\n"
body := "[security]\nJWT_SECRET = "+testJWTSecret+"\n\n[app]\nDEV_MODE = true\nSITE_URL = https://forum.example.com/\nCORS_ORIGINS = https://a.example.com, https://b.example.com/\n"
if err := os.WriteFile(filepath.Join(work, "app.ini"), []byte(body), 0600); err != nil {
t.Fatal(err)
}