增加图形验证码的功能
This commit is contained in:
@@ -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 | never;login 场景由 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 {
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user