package auth import ( "sync" "time" ) // Limiter 是按键(IP / 用户)计数的滑动窗口限流器。 // 进程内内存实现:现场单实例部署足够,不引入额外存储。 type Limiter struct { mu sync.Mutex hits map[string][]time.Time limit int window time.Duration now func() time.Time } // NewLimiter 创建限流器;limit <= 0 表示不限流。 func NewLimiter(limit int, window time.Duration, now func() time.Time) *Limiter { if now == nil { now = time.Now } return &Limiter{hits: make(map[string][]time.Time), limit: limit, window: window, now: now} } // Allow 记录一次访问并报告是否放行。 func (l *Limiter) Allow(key string) bool { if l == nil || l.limit <= 0 { return true } now := l.now() cutoff := now.Add(-l.window) l.mu.Lock() defer l.mu.Unlock() kept := l.hits[key][:0] for _, t := range l.hits[key] { if t.After(cutoff) { kept = append(kept, t) } } if len(kept) >= l.limit { l.hits[key] = kept return false } l.hits[key] = append(kept, now) return true } // Reset 清空某个键的计数,例如登录成功后不再累计失败次数。 func (l *Limiter) Reset(key string) { if l == nil { return } l.mu.Lock() delete(l.hits, key) l.mu.Unlock() }