fix: 完善腾讯验证码区域适配与 CSP 白名单

修复国内站和国际站 SDK 构造、验证容器、票据重置及动态资源加载问题,并补充认证流程回归测试。
This commit is contained in:
shaw
2026-08-06 20:34:37 +08:00
parent a19c9f8d8a
commit 8e102b3a0f
42 changed files with 922 additions and 70 deletions
@@ -168,6 +168,7 @@ func (h *SettingHandler) GetSettings(c *gin.Context) {
TencentCaptchaAppSecretKeyConfigured: settings.TencentCaptchaAppSecretKeyConfigured,
TencentCaptchaCloudSecretIDConfigured: settings.TencentCaptchaCloudSecretIDConfigured,
TencentCaptchaCloudSecretKeyConfigured: settings.TencentCaptchaCloudSecretKeyConfigured,
TencentCaptchaRegion: settings.TencentCaptchaRegion,
AliyunCaptchaEnabled: settings.AliyunCaptchaEnabled,
AliyunCaptchaAccessKeyID: settings.AliyunCaptchaAccessKeyID,
AliyunCaptchaAccessKeySecretConfigured: settings.AliyunCaptchaAccessKeySecretConfigured,
@@ -122,6 +122,9 @@ func diffSettings(before *service.SystemSettings, after *service.SystemSettings,
if req.TencentCaptchaCloudSecretKey != "" {
changed = append(changed, "tencent_captcha_cloud_secret_key")
}
if before.TencentCaptchaRegion != after.TencentCaptchaRegion {
changed = append(changed, "tencent_captcha_region")
}
if before.AliyunCaptchaEnabled != after.AliyunCaptchaEnabled {
changed = append(changed, "aliyun_captcha_enabled")
}
@@ -121,6 +121,43 @@ func TestUpdateSettingsRetainsStoredTencentCaptchaCredentialsWhenInputsEmpty(t *
require.Equal(t, "stored-cloud-secret-key", repo.values[service.SettingKeyTencentCaptchaCloudSecretKey])
}
// 天御站点决定前端加载哪个 SDK 与服务端打哪个接入点,两端必须一致。
// 部分载荷把它重置回中国站,会让已配国际站的部署在下一次任意保存后整体失效。
func TestUpdateSettingsPartialPayloadKeepsTencentCaptchaRegion(t *testing.T) {
h, repo := newStepUpSwitchTestHandler(t, map[string]string{
service.SettingKeyTencentCaptchaRegion: service.TencentCaptchaRegionINTL,
})
rec := doUpdateSettings(t, h, map[string]any{"risk_control_enabled": true}, nil)
require.Equal(t, http.StatusOK, rec.Code)
require.Equal(t, service.TencentCaptchaRegionINTL,
repo.values[service.SettingKeyTencentCaptchaRegion])
}
func TestUpdateSettingsNormalizesUnknownTencentCaptchaRegion(t *testing.T) {
h, repo := newStepUpSwitchTestHandler(t, map[string]string{
service.SettingKeyTencentCaptchaRegion: service.TencentCaptchaRegionINTL,
})
rec := doUpdateSettings(t, h, map[string]any{"tencent_captcha_region": "sgp"}, nil)
require.Equal(t, http.StatusOK, rec.Code)
require.Equal(t, service.TencentCaptchaRegionCN,
repo.values[service.SettingKeyTencentCaptchaRegion],
"未知站点必须落回中国站,不能写入无法识别的值")
}
func TestUpdateSettingsWritesTencentCaptchaRegionWhenSent(t *testing.T) {
h, repo := newStepUpSwitchTestHandler(t, map[string]string{})
rec := doUpdateSettings(t, h, map[string]any{"tencent_captcha_region": "intl"}, nil)
require.Equal(t, http.StatusOK, rec.Code)
require.Equal(t, service.TencentCaptchaRegionINTL,
repo.values[service.SettingKeyTencentCaptchaRegion])
}
func TestUpdateSettingsValidatesTencentCaptchaAppIDWhenEnabledFlagIsOmitted(t *testing.T) {
h, _ := newStepUpSwitchTestHandler(t, map[string]string{
service.SettingKeyTencentCaptchaEnabled: "true",
@@ -60,6 +60,7 @@ type UpdateSettingsRequest struct {
TencentCaptchaAppSecretKey string `json:"tencent_captcha_app_secret_key"`
TencentCaptchaCloudSecretID string `json:"tencent_captcha_cloud_secret_id"`
TencentCaptchaCloudSecretKey string `json:"tencent_captcha_cloud_secret_key"`
TencentCaptchaRegion string `json:"tencent_captcha_region"`
// 阿里云验证码 2.0 设置
AliyunCaptchaEnabled bool `json:"aliyun_captcha_enabled"`
@@ -644,6 +645,13 @@ func (h *SettingHandler) UpdateSettings(c *gin.Context) {
if req.AliyunCaptchaRegion != service.AliyunCaptchaRegionSGP {
req.AliyunCaptchaRegion = service.AliyunCaptchaRegionCN
}
// 天御站点 normalize:未发送保留已存值,非法值一律按中国站落库
if _, sent := sentFields["tencent_captcha_region"]; !sent {
req.TencentCaptchaRegion = previousSettings.TencentCaptchaRegion
}
if req.TencentCaptchaRegion != service.TencentCaptchaRegionINTL {
req.TencentCaptchaRegion = service.TencentCaptchaRegionCN
}
// Turnstile 参数验证
if req.TurnstileEnabled {
@@ -1501,6 +1509,7 @@ func (h *SettingHandler) UpdateSettings(c *gin.Context) {
TencentCaptchaAppSecretKey: req.TencentCaptchaAppSecretKey,
TencentCaptchaCloudSecretID: req.TencentCaptchaCloudSecretID,
TencentCaptchaCloudSecretKey: req.TencentCaptchaCloudSecretKey,
TencentCaptchaRegion: req.TencentCaptchaRegion,
AliyunCaptchaEnabled: req.AliyunCaptchaEnabled,
AliyunCaptchaAccessKeyID: req.AliyunCaptchaAccessKeyID,
AliyunCaptchaAccessKeySecret: req.AliyunCaptchaAccessKeySecret,
@@ -2084,6 +2093,7 @@ func (h *SettingHandler) UpdateSettings(c *gin.Context) {
TencentCaptchaAppSecretKeyConfigured: updatedSettings.TencentCaptchaAppSecretKeyConfigured,
TencentCaptchaCloudSecretIDConfigured: updatedSettings.TencentCaptchaCloudSecretIDConfigured,
TencentCaptchaCloudSecretKeyConfigured: updatedSettings.TencentCaptchaCloudSecretKeyConfigured,
TencentCaptchaRegion: updatedSettings.TencentCaptchaRegion,
AliyunCaptchaEnabled: updatedSettings.AliyunCaptchaEnabled,
AliyunCaptchaAccessKeyID: updatedSettings.AliyunCaptchaAccessKeyID,
AliyunCaptchaAccessKeySecretConfigured: updatedSettings.AliyunCaptchaAccessKeySecretConfigured,