middleware: - 拆分 auth.go → auth.go + auth_token.go + auth_parser.go + auth_admin.go - 拆分 csrf.go → csrf.go + csrf_token.go - 拆分 ratelimit.go → ratelimit.go + ratelimit_core.go + ratelimit_cleanup.go - 修复 import 未使用/缺失问题 router: - 拆分 router.go → admin.go + api.go + frontend.go + deps_core.go + deps_extra.go feat(admin): 站点设置管理页面 - 新增 SSR 页面 /admin/site-settings(仅 Owner) - 审核开关 Toggle 即时保存 - 通用设置展示 - 侧边栏新增站点设置入口 - 注册 UpdateBoolSetting/GetBoolSetting API 路由
33 lines
1.0 KiB
Go
33 lines
1.0 KiB
Go
package middleware
|
||
|
||
import "sync"
|
||
|
||
// RateLimiter 双维度滑动窗口登录限流
|
||
// 维度一(账户):同邮箱 1 分钟内失败 3 次 → 锁定 1 分钟
|
||
// 维度二(IP):同 IP 1 分钟内失败 10 次 → 锁定 1 分钟
|
||
type RateLimiter struct {
|
||
mu sync.RWMutex
|
||
accountFailures map[string]*windowState
|
||
ipFailures map[string]*windowState
|
||
}
|
||
|
||
// NewRateLimiter 创建限流器并启动后台清理
|
||
func NewRateLimiter() *RateLimiter {
|
||
rl := &RateLimiter{
|
||
accountFailures: make(map[string]*windowState),
|
||
ipFailures: make(map[string]*windowState),
|
||
}
|
||
go rl.cleanupLoop()
|
||
return rl
|
||
}
|
||
|
||
// AllowAccount 检查账户维度是否允许登录尝试
|
||
func (rl *RateLimiter) AllowAccount(email string) (RateLimitResult, func()) {
|
||
return rl.check(rl.accountFailures, email, accountWindow, accountBlockDur, accountMaxFails, true)
|
||
}
|
||
|
||
// AllowIP 检查 IP 维度是否允许登录尝试
|
||
func (rl *RateLimiter) AllowIP(ip string) (RateLimitResult, func()) {
|
||
return rl.check(rl.ipFailures, ip, ipWindow, ipBlockDur, ipMaxFails, false)
|
||
}
|