增加图形验证码的功能

This commit is contained in:
2026-08-01 00:05:04 +08:00
parent 97450f0739
commit 4f00b83e86
15 changed files with 838 additions and 2 deletions

View File

@@ -21,6 +21,7 @@ type Config struct {
I18n *I18nConfig `json:"i18n"`
RateLimit *RateLimitConfig `json:"rateLimit"`
MCP *MCPConfig `json:"mcp"`
Captcha *CaptchaConfig `json:"captcha"`
}
// I18nConfig 国际化配置
@@ -308,6 +309,48 @@ func (c *LoggerConfig) IsAsync() bool {
return *c.Async
}
// CaptchaConfig 图形验证码配置可选模块enabled=false 或未配置时不启用)
type CaptchaConfig struct {
// Enabled 总开关
Enabled bool `json:"enabled"`
// Length 验证码字符数,默认 4
Length int `json:"length"`
// Width 图片宽度(像素),默认 120
Width int `json:"width"`
// Height 图片高度(像素),默认 40
Height int `json:"height"`
// TTLSec 验证码有效期(秒),默认 300
TTLSec int `json:"ttlSec"`
// Login 登录防暴力配置(失败 N 次后要求验证码M 次后锁定)
Login *LoginCaptchaConfig `json:"login"`
// Scenes 各场景是否强制图形验证码mode: always | neverlogin 场景由 Login 配置控制)
Scenes map[string]CaptchaSceneConfig `json:"scenes"`
}
// LoginCaptchaConfig 登录防暴力配置
type LoginCaptchaConfig struct {
// ShowAfterFailures 失败多少次后开始要求图形验证码,默认 3
ShowAfterFailures int `json:"showAfterFailures"`
// LockAfterFailures 失败多少次后临时锁定,默认 10
LockAfterFailures int `json:"lockAfterFailures"`
// LockDurationMin 锁定时长(分钟),默认 30
LockDurationMin int `json:"lockDurationMin"`
}
// CaptchaSceneConfig 单场景验证码策略
type CaptchaSceneConfig struct {
// Mode always=该场景始终要求图形验证码never=不要求login 场景忽略此项)
Mode string `json:"mode"`
}
// RateLimitConfig 限流配置
type RateLimitConfig struct {
// Enable 是否启用限流
@@ -544,6 +587,34 @@ func (c *Config) setDefaults() {
c.MCP.CallTimeoutSeconds = 60
}
}
// Captcha 默认值
if c.Captcha != nil {
if c.Captcha.Length == 0 {
c.Captcha.Length = 4
}
if c.Captcha.Width == 0 {
c.Captcha.Width = 120
}
if c.Captcha.Height == 0 {
c.Captcha.Height = 40
}
if c.Captcha.TTLSec == 0 {
c.Captcha.TTLSec = 300
}
if c.Captcha.Login == nil {
c.Captcha.Login = &LoginCaptchaConfig{}
}
if c.Captcha.Login.ShowAfterFailures == 0 {
c.Captcha.Login.ShowAfterFailures = 3
}
if c.Captcha.Login.LockAfterFailures == 0 {
c.Captcha.Login.LockAfterFailures = 10
}
if c.Captcha.Login.LockDurationMin == 0 {
c.Captcha.Login.LockDurationMin = 30
}
}
}
// GetDatabase 获取数据库配置
@@ -603,6 +674,11 @@ func (c *Config) GetMCP() *MCPConfig {
return c.MCP
}
// GetCaptcha 获取图形验证码配置
func (c *Config) GetCaptcha() *CaptchaConfig {
return c.Captcha
}
// GetDatabaseDSN 获取数据库连接字符串
func (c *Config) GetDatabaseDSN() (string, error) {
if c.Database == nil {

View File

@@ -90,6 +90,23 @@
"byIP": true,
"byUserID": false
},
"captcha": {
"enabled": false,
"length": 4,
"width": 120,
"height": 40,
"ttlSec": 300,
"login": {
"showAfterFailures": 3,
"lockAfterFailures": 10,
"lockDurationMin": 30
},
"scenes": {
"register": { "mode": "always" },
"change_phone": { "mode": "always" },
"send_sms": { "mode": "always" }
}
},
"mcp": {
"enabled": true,
"callTimeoutSeconds": 60,