Nginx可通过协议层特征对请求参数做轻量合法性筛查:检查关键参数是否存在及命名规范、限制参数数量与总长度、校验参数值基础格式、结合Referer/Host/方法做上下文校验,但不替代后端业务校验。

Nginx 本身不解析请求体内容,也不执行业务逻辑校验,但它可以通过协议层特征对请求参数做轻量、快速、可落地的合法性筛查——重点不是“参数值是否业务正确”,而是“参数是否存在、命名是否合规、格式是否像合法请求”。
检查关键参数是否存在且命名规范
很多自动化攻击或低质量爬虫会省略必需参数,或使用非法命名(如含空格、控制字符、重复键)。Nginx 可用内置变量和正则提前拦截:
- 使用
$arg_xxx获取指定参数值,配合if判断是否为空:if ($arg_token = "") { return 400; } - 拦截含非法字符的参数名(如空格、
%00、{、}):if ($args ~ "[ s{}\|<>'"]") { return 400; } - 防止重复参数干扰(如
?id=1&id=2),虽 Nginx 默认取第一个,但可加日志标记异常:log_format bad_args '$remote_addr - $request_args $args';
限制参数数量与总长度防爆破和畸形构造
单个请求携带上百个参数通常是扫描或 fuzz 行为:
- 用
$args长度粗筛:if ($args = "") { return 400; }(强制非空) - 控制总长度(避免 URL 过长触发缓冲区问题):
if ($args !~ "^[a-zA-Z0-9_=&%.+-]{1,2048}$") { return 414; } - 限制参数个数(需配合 Lua 或 OpenResty;纯 Nginx 可用
$query_string统计&数量近似判断)
校验参数值格式是否符合基础模式
不验证业务含义,但可拦截明显非法格式:
- ID 类参数应为数字:
if ($arg_id !~ "^[1-9][0-9]*$") { return 400; } - 时间戳应为 10 或 13 位数字:
if ($arg_ts !~ "^([1-9][0-9]{9}|[1-9][0-9]{12})$") { return 400; } - 邮箱类参数仅作简单结构检查(不替代后端验证):
if ($arg_email !~ "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+.[a-zA-Z]{2,}$") { return 400; }
结合 Referer、Host 和请求方法做上下文一致性校验
参数合理性需放在请求上下文中看:
- POST 请求带敏感操作参数(如
action=delete)但 Referer 为空或异常:valid_referers none blocked example.com *.example.com; if ($invalid_referer && $request_method = POST && $arg_action = "delete") { return 403; } - GET 请求却携带超长
data=参数(疑似伪装 POST):if ($request_method = GET && $arg_data ~ "^[a-zA-Z0-9+/]{1000,}$") { return 400; }
注意边界与局限
-
$arg_xxx自动解码一次,但无法处理双重编码(如%252e),需在前端规范编码; - 所有
if判断应在location块内,避免在server或http级别误触发; - 不替代后端校验,仅作为第一道过滤网,防止无效请求打满后端;
- 复杂逻辑(如签名验签、JSON Schema 校验)必须由后端或 OpenResty 扩展完成。


















