增加密码解锁与游客签名 cookie;发帖页对齐 1440 并默认双栏预览;修复 locked 解析、按钮对比度与回复聚焦。 Co-authored-by: Cursor <cursoragent@cursor.com>
88 lines
2.1 KiB
Go
88 lines
2.1 KiB
Go
package service
|
||
|
||
import (
|
||
"sync"
|
||
"time"
|
||
)
|
||
|
||
// RateLimiter 内存速率限制器
|
||
type RateLimiter struct {
|
||
mu sync.Mutex
|
||
records map[string][]time.Time
|
||
limits map[string]int // key -> 每分钟最大请求数
|
||
cooldown map[string]time.Duration
|
||
}
|
||
|
||
func NewRateLimiter() *RateLimiter {
|
||
return &RateLimiter{
|
||
records: make(map[string][]time.Time),
|
||
limits: make(map[string]int),
|
||
cooldown: make(map[string]time.Duration),
|
||
}
|
||
}
|
||
|
||
// SetLimit 设置某类请求的每分钟限制
|
||
func (r *RateLimiter) SetLimit(key string, perMinute int) {
|
||
r.mu.Lock()
|
||
defer r.mu.Unlock()
|
||
r.limits[key] = perMinute
|
||
}
|
||
|
||
// Allow 检查是否允许请求
|
||
func (r *RateLimiter) Allow(key string) bool {
|
||
r.mu.Lock()
|
||
defer r.mu.Unlock()
|
||
|
||
limit, ok := r.limits[key]
|
||
if !ok {
|
||
return true
|
||
}
|
||
|
||
now := time.Now()
|
||
windowStart := now.Add(-1 * time.Minute)
|
||
|
||
// 清理过期记录
|
||
records := r.records[key]
|
||
valid := records[:0]
|
||
for _, t := range records {
|
||
if t.After(windowStart) {
|
||
valid = append(valid, t)
|
||
}
|
||
}
|
||
|
||
if len(valid) >= limit {
|
||
r.records[key] = valid
|
||
return false
|
||
}
|
||
|
||
valid = append(valid, now)
|
||
r.records[key] = valid
|
||
return true
|
||
}
|
||
|
||
// 速率限制类型常量
|
||
const (
|
||
RateLogin = "login"
|
||
RateRegister = "register"
|
||
RatePost = "post"
|
||
RateComment = "comment"
|
||
RateChat = "chat" // 群聊发消息
|
||
RateUpload = "upload" // 帖子插图等上传
|
||
RateInteract = "interact" // 投票/抽奖/解锁等互动
|
||
RateHidePassword = "hide_password" // 密码隐藏块尝试
|
||
)
|
||
|
||
// DefaultRateLimiter 创建默认速率限制器
|
||
func DefaultRateLimiter() *RateLimiter {
|
||
rl := NewRateLimiter()
|
||
rl.SetLimit(RateLogin, 20) // 登录 20/分钟
|
||
rl.SetLimit(RateRegister, 10) // 注册 10/分钟
|
||
rl.SetLimit(RatePost, 10) // 发帖 10/分钟
|
||
rl.SetLimit(RateComment, 30) // 评论 30/分钟
|
||
rl.SetLimit(RateChat, 30) // 群聊消息 30/分钟
|
||
rl.SetLimit(RateUpload, 20) // 图片上传 20/分钟
|
||
rl.SetLimit(RateInteract, 40) // 互动 40/分钟
|
||
rl.SetLimit(RateHidePassword, 20) // 密码尝试 20/分钟(按 IP)
|
||
return rl
|
||
}
|