"""限流中间件 — 登录 5 次/min + 写接口按用户限流。""" import time from collections import defaultdict from fastapi import HTTPException, Request, status class RateLimiter: """简单的内存限流器。""" def __init__(self) -> None: self._requests: dict[str, list[float]] = defaultdict(list) def check(self, key: str, max_requests: int, window_seconds: int) -> bool: """检查是否超过限流阈值。""" now = time.time() window_start = now - window_seconds # 清理过期记录 self._requests[key] = [t for t in self._requests[key] if t > window_start] if len(self._requests[key]) >= max_requests: return False self._requests[key].append(now) return True rate_limiter = RateLimiter() async def login_rate_limit(request: Request) -> None: """登录接口限流 — 5 次/min/IP。""" client_ip = request.client.host if request.client else "unknown" if not rate_limiter.check(f"login:{client_ip}", max_requests=5, window_seconds=60): raise HTTPException( status_code=status.HTTP_429_TOO_MANY_REQUESTS, detail="登录尝试过于频繁,请稍后再试", headers={"Retry-After": "60"}, )