nginx层sql注入防护仅为初步过滤,需在server或location ~ .php$块中用if匹配已解码的$args和原始$request_uri,配合return 403拦截;严禁用$request_body、rewrite或未转义正则;根本防护必须依赖php层pdo预处理、禁用高危函数及最小权限数据库账号。

在 Windows 环境下用 Nginx 1.31.6 + PHP 8.4.1 搭建 Web 服务时,Nginx 层的 SQL 注入防护只能做“初步过滤”,它不解析 SQL、看不到 POST 请求体、也无法替代 PHP 层的安全机制。配置重点是:只匹配 $args(已解码查询参数)和 $request_uri(原始 URI,含编码),避免误杀与规则失效。
只在 server 或 location 块内写 if 规则
Nginx 的 if 不支持嵌套,也不能放在 http 块顶层——那样规则不会生效或被重复触发。应放在具体站点的 server 块里,或更精确地放在处理动态请求的 location ~ \.php$ 块中:
- 确保规则作用域明确,比如:
server { listen 80; server_name example.com; ... } - 不要在
location /api/外围写通用规则,除非你确认所有接口都走相同路径 - 若使用 FastCGI,
$args已由 Nginx 自动解码,正则应匹配明文内容(如or 1=1),而非编码形式
推荐的轻量级拦截规则(防明显攻击特征)
以下规则放在 server 块内,用 return 403 终止请求,不重定向、不 rewrite(避免绕过):
if ($args ~* "(%27)|(')|(--)|(%23)|(#)|\b(select|union|insert|update|delete|drop|exec|declare)\b") { return 403; }if ($request_uri ~* "(%20OR%20|%20AND%20|/\*|\*/|;\s*(select|union)\s+from)") { return 403; }-
if ($args ~* "['\";]+") { return 403; }(拦截常见危险符号组合)
注意:\b 保证只匹配完整单词,避免把 user_id 里的 id 当成注入;%20OR%20 比单纯 OR 更可靠,因空格常被 URL 编码。
必须避开的典型错误
这些操作会让规则完全失效或引入新风险:
- 写
if ($request_body ~ ...)—— 默认配置下$request_body为空,规则永远不触发 - 用
rewrite ... break替代return 403—— 攻击者可能通过重定向链绕过检测 - 正则中漏转义特殊字符,比如写
select|union|delete却没加反斜杠,.、+、(、)都需转义才能按字面匹配 - 在
location ~ \.php$中写规则却用$request_uri匹配未解码内容,而实际请求可能是/index.php?id=1%20union%20select,此时应优先用$args解析后判断
真正起效的防护必须落在 PHP 层
Nginx 规则只是最外层筛子,不能代替代码层防御。PHP 8.4.1 下必须做到:
- 全部数据库操作使用 PDO 预处理语句,绑定参数:
$stmt = $pdo->prepare("SELECT * FROM users WHERE id = ?"); $stmt->execute([$id]); - 禁用高危函数:在
php.ini中设置disable_functions = exec,system,passthru,shell_exec,eval,assert,proc_open,popen - 数据库账号最小权限:仅授予
SELECT、INSERT等必要权限,禁用DROP、CREATE、EXECUTE - 关闭错误回显:
display_errors = Off,防止泄露表结构或路径信息
不复杂但容易忽略
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











