正文边缘限流是防止暴力尝试与滥用的关键控制。本文在 Next.js 15 的中间件中实现令牌桶限流与标准化响应头,适用于公共 API 与登录、验证码等敏感端点。一、令牌桶实现与中间件接入import { NextRequest, NextResponse } from 'next/server' type State = { tokens: number; updatedAt: number } const CAPACITY = 60 const REFILL_PER_SEC = 1 const store: Map<string, State> = (globalThis as any).__rl_store || new Map() ;(globalThis as any).__rl_store = store function ipOf(req: NextRequest) { const xff = req.headers.get('x-forwarded-for') || '' const cfip = req.headers.get('cf-connecting-ip') || '' const ip = (xff.split(',')[0] || cfip || '0.0.0.0').trim() return ip } function allow(ip: string) { const now = Date.now() const st = store.get(ip) || { tokens: CAPACITY, updatedAt: now } const elapsed = Math.max(0, (now - st.updatedAt) / 1000) const refill = Math.floor(elapsed * REFILL_PER_SEC) st.tokens = Math.min(CAPACITY, st.tokens + refill) st.updatedAt = refill > 0 ? now : st.updatedAt if (st.tokens <= 0) { store.set(ip, st) return { ok: false, resetSec: Math.ceil((CAPACITY - st.tokens) / REFILL_PER_SEC) } } st.tokens -= 1 store.set(ip, st) return { ok: true, remaining: st.tokens } } export function middleware(req: NextRequest) { const ip = ipOf(req) const result = allow(ip) if (!result.ok) { return new NextResponse('Too Many Requests', { status: 429, headers: { 'Cache-Control': 'no-store', 'Retry-After': String(result.resetSec), 'RateLimit-Limit': String(CAPACITY), 'RateLimit-Remaining': '0', 'RateLimit-Reset': String(result.resetSec) } }) } const res = NextResponse.next() res.headers.set('RateLimit-Limit', String(CAPACITY)) res.headers.set('RateLimit-Remaining', String(result.remaining || 0)) res.headers.set('RateLimit-Reset', '1') res.headers.set('Cache-Control', 'no-store') return res } 二、治理要点标准头:返回 `RateLimit-*` 与 `Retry-After`,便于客户端与网关协同退避。缓存策略:统一 `Cache-Control: no-store` 避免 429 被误缓存。识别来源:优先 `x-forwarded-for`,其次 `cf-connecting-ip`;如有代理需在边缘正确透传。细粒度:对高风险端点(登录、验证码、敏感 API)可配置更小容量与更严格窗口。

点赞(0) 打赏

评论列表 共有 0 条评论

暂无评论
立即
投稿

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部