NGINX下PHP应用部分路由返回403求助:请求未转发至dispatch.php
咱们先从你的配置和现象入手分析:主页和/systems/能正常访问,但/login/返回403,这大概率是Nginx处理目录请求的逻辑导致的,结合你的配置来拆解:
问题根源分析
你的location /块里用了try_files $uri $uri/ /dispatch.php$is_args$args;,这个规则的执行顺序是:
- 先检查请求对应的文件是否存在(比如
/login/会先找/var/www/login这个文件) - 如果文件不存在,再检查对应的目录是否存在(也就是
/var/www/login/目录) - 前两个都不满足,才转发到
dispatch.php
当/var/www/login/目录实际存在时,Nginx会尝试访问这个目录的索引文件(你配置的index dispatch.php),但如果这个目录里没有dispatch.php,且Nginx默认关闭了目录索引(autoindex off),就会返回403 Forbidden。而/systems/对应的目录不存在,所以直接走到第三步,转发到dispatch.php,自然能正常工作。
另外还有一种可能:Nginx的运行用户(通常是www-data)没有权限读取/var/www/login/目录,即使目录存在也会返回403,但考虑到其他路由正常,这种概率稍低,但也需要排查。
解决方案
根据你的单入口PHP应用需求,推荐以下几种解决方式:
方案1:移除$uri/,强制所有请求走单入口(最推荐)
既然你的应用所有请求都要转发到dispatch.php,完全不需要Nginx尝试访问实际目录,直接修改location /块:
location / { try_files $uri /dispatch.php$is_args$args; }
这样Nginx只会检查请求对应的文件是否存在,不存在就直接转发到dispatch.php,彻底避免目录触发的403问题。
方案2:修复目录权限与索引配置(如果必须保留实际目录)
如果服务器上确实需要存在/login/这类目录,那么:
- 确保目录索引指向你的单入口文件,同时保持目录索引关闭:
location / { try_files $uri $uri/ /dispatch.php$is_args$args; index dispatch.php; autoindex off; }
- 给Nginx运行用户赋予目录的读取权限:
chown -R www-data:www-data /var/www chmod -R 755 /var/www
方案3:单独处理以斜杠结尾的目录请求
添加一个专门的规则,强制所有以/结尾的请求直接转发到dispatch.php:
# 处理所有以斜杠结尾的目录请求 location ~ /$ { rewrite ^ /dispatch.php$is_args$args last; } location / { try_files $uri /dispatch.php$is_args$args; }
验证修改
修改配置后,别忘了重启Nginx生效:
nginx -s reload
然后测试/login/路由,应该就能正常转发到dispatch.php了。
内容的提问来源于stack exchange,提问作者Rohit

