Nginx处理.php请求需严格匹配路径、正确构造SCRIPT_FILENAME、使用fastcgi_pass而非http代理,并禁用备份文件执行以防源码泄露;.jsp则须用proxy_pass转发至Java容器,不可混用FastCGI。

要让 Nginx 正确把 .php 或 .jsp 请求交给 FastCGI 服务处理,核心不是“加个后缀匹配就行”,而是匹配逻辑、路径构造、协议适配三者必须严丝合缝。尤其注意:.jsp 不是 PHP-FPM 能处理的,它需搭配 Tomcat 或 Jetty 等 Java 容器,Nginx 仅作反向代理;而 .php 必须走 FastCGI 协议,不能错写成 http:// 地址。
匹配规则要防误伤,不只看后缀
单纯用 location ~ \.php$ 看似简单,但存在风险:
- 会匹配到
/static/logo.php.bak或/config.php.swp这类备份文件,导致源码泄露 - 无法支持现代框架路由(如
/index.php/api/user),因为$锚定结尾,截断了 PATH_INFO - 若 URI 是
/app.php/test,该规则直接不命中
更稳妥写法是:
-
location ~ \.php(/|$):兼容/index.php和/index.php/path两种形态 -
location ~ ^/.+\.php(/|$):强制开头为/,避免匹配到类似/file.jpg.php的畸形路径 - 对 .jsp,Nginx 不走 FastCGI,应改用
proxy_pass转发至 Tomcat(如proxy_pass http://127.0.0.1:8080;),且需单独 location 块隔离,避免与 PHP 规则冲突
SCRIPT_FILENAME 构造必须真实可访问
Nginx 不解析 PHP,只是把请求转给 PHP-FPM;而 PHP-FPM 需要确切知道磁盘上脚本的完整路径。漏设或错设 SCRIPT_FILENAME,90% 会报 “Primary script unknown” 或 502。
立即学习“PHP免费学习笔记(深入)”;
- ✅ 推荐写法:
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
→$realpath_root自动解析符号链接和 alias 后的真实物理路径,比$document_root更健壮 - ❌ 常见错误:
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
→ 若用了alias指令,$document_root为空或错值,必然失败 - ❌ 绝对禁止硬编码:
fastcgi_param SCRIPT_FILENAME /var/www/html$fastcgi_script_name;
→ 失去配置复用性,迁移即崩
fastcgi_pass 地址格式不能加 http://
fastcgi_pass 不是 HTTP 代理,它指定的是 FastCGI 进程监听的通信端点,协议是 FastCGI,不是 HTTP。
- ✅ 正确形式只有两种:
• TCP 方式:fastcgi_pass 127.0.0.1:9000;(要求 PHP-FPM 的listen = 127.0.0.1:9000)
• Unix socket(推荐):fastcgi_pass unix:/run/php/php8.2-fpm.sock;(性能更高,无网络栈开销) - ❌ 错误示例:
fastcgi_pass http://127.0.0.1:9000;
→ Nginx 直接报错:invalid URL prefix in "http://127.0.0.1:9000" - ⚠️ 注意权限:
.sock文件需被 nginx worker 进程用户(如 www-data)可读写,SELinux 或 systemd socket 单元配置不当也会导致连接拒绝
安全兜底:防源码泄露 + 拒绝非法请求
光能转发不够,还要堵住常见攻击面:
- 在 PHP location 块内加
try_files $uri =404;,确保请求的 .php 文件真实存在,否则直接返回 404,不交由 PHP-FPM 处理——防止利用不存在脚本触发 FPM 异常或日志污染 - 上传目录(如
/uploads/)、配置目录(如/config/)必须禁用 PHP 执行:location ^~ /uploads/ {<br> deny all;<br>}
或更细粒度:location ~ ^/uploads/.*\.php$ { return 403; } - PHP-FPM 层也要同步加固:检查
security.limit_extensions = .php .phtml,避免攻击者上传shell.php7绕过 Nginx 匹配却仍被 FPM 执行



















