最常用有效的接口级高频防护方式是用 $request_uri 配合 limit_req_zone。在 http 块定义限流规则:limit_req_zone $request_uri zone=byuri:10m rate=3r/s;按需选用 $request_uri(含参)或 $uri(不含参);在 location 中精准启用,如 location = /api/login { limit_req zone=byuri burst=5 nodelay; };burst 允许短时突发,nodelay 使超限请求立即返回 503;注意 URI 大小写、编码一致性;通过 access_log 中 $limit 变量验证效果。

直接用 $request_uri 配合 limit_req_zone,是最常用也最有效的接口级高频防护方式。它不干扰全站流量,只盯住登录、下单、短信发送这类高危路径,既防刷又不卡正常用户。
在 http 块中定义 URI 级限流规则
必须写在全局 http{} 块内,不能放在 server 或 location 里:
limit_req_zone $request_uri zone=byuri:10m rate=3r/s;-
$request_uri包含路径和参数(如/api/login?from=app),适合区分不同调用来源 - 若只需按路径不看参数,改用
$uri(如/api/login),避免同一接口因参数不同被拆成多个计数桶 -
zone=byuri:10m分配 10MB 内存,约可支撑数万个不同 URI 的状态记录 -
rate=3r/s表示每个唯一 URI 每秒最多处理 3 个请求,对敏感操作足够严格
在 location 中精准启用该规则
只对真实风险路径生效,比如:
location = /api/login { limit_req zone=byuri burst=5 nodelay; }location ^~ /admin/ { limit_req zone=byuri burst=8 nodelay; }-
location ~* \.(php|jsp)$ { limit_req zone=byuri burst=2 nodelay; }(防动态脚本暴力访问) -
burst=5允许短时多发 5 次,覆盖页面加载或前端重试等合理场景 -
nodelay让超限请求立刻返回 503,不排队、不拖慢响应,压缩攻击者试探窗口
注意 URI 提取细节,避免误放行或误拦截
真实请求中 URI 可能带参、编码或大小写差异,需提前对齐:
- Nginx 默认区分大小写,
/Api/Login和/api/login会被视为两个 URI;如需统一,可在 location 中用rewrite标准化,或改用$uri+ 正则匹配 - 含中文或特殊符号的 URI 会自动编码,
$request_uri保留原始编码形式,确保限流键一致 - 若后端依赖 query string 做鉴权(如带 sign 参数),建议用
$request_uri;若仅防护路径本身,用$uri更省内存且逻辑清晰
配合日志快速验证与调优
上线后靠日志确认是否生效、是否误伤:
- 在 access_log 格式中加入
$limit变量,例如:log_format main '$remote_addr - $remote_user [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent" "$limit";' - 被限流的请求会在日志末尾显示对应 zone 名(如
byuri),未限流则为空 - 初始建议设宽松值(如
rate=10r/s+burst=20),观察 1–2 天真实峰值后再逐步收紧

















