我正在从 Apache 切换到 Nginx/fcgi,在尝试设置应用程序重写规则时遇到了一个小问题。
代码通过使用 PATH_INFO 来处理路由,例如 example.com/foo/bar/ 将被路由到 example.com/index.php/foo/bar/
我已经修改了服务器配置以传递PATH_INFO:
location ~ \.php$ {
include /etc/nginx/fastcgi_params;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_split_path_info ^(.+\.php)(.*)$;
fastcgi_param SCRIPT_FILENAME /var/www/public$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_param PATH_TRANSLATED $document_root$fastcgi_path_info;
}
重写处理程序:
location / {
root /var/www/public;
index index.html index.htm index.php;
if (!-f $request_filename) {
rewrite ^(.*)/(.*)$ /index.php/$2 break;
}
}
和 '重写登录',该 URL 似乎路由正确:
[error]: *2 open() "/var/www/public/index.php/test" failed (20: Not a directory), client: 192.168.0.254, server: example.com, request: "GET /test HTTP/1.1", host: "example.com", referrer: "http://example.com/index.php"
然而,它似乎正在寻找目录“test”。我如何强制它请求index.php,并将'/test'传递给脚本?
答案1
看起来您正在遵循一个非常过时的糟糕教程(if (!-f
通常不推荐,有try_files
更好的替代品)。您遇到了许多问题:
第一的您在location /
上下文中有指令,这些指令应该在server
上下文中,这样您就可以避免SCRIPT_FILENAME
变量中的路径重复。
第二,您在重写中使用该break
标志;这意味着它不应重新评估位置匹配。这实际上使请求永远不会离开块location /
,而是被视为静态文件请求。
第三,看看你的location ~ \.php$ {
:Nginx 根据 URI 匹配位置,并且你明确告诉 Nginx 只处理以 结尾的 URI .php
,但如果你重写为,index.php/test/
那么它就不会触发。
最后,而您使用的是 ,PATH_INFO
而您应该使用REQUEST_URI
。区别在于,要使 PATH_INFO 工作,您必须告诉 Nginx 将任何带有 的请求传递.php
给 PHP,然后 PHP 必须找到正确的文件。
这意味着您允许example.org/uploads/image.jpg/index.php
向 PHP 发送类似这样的请求,并且还允许 PHP 执行文件/uploads/image.jpg
。如果恶意用户上传了包含 PHP 的文件,他们现在就可以在您的服务器上执行任意代码。这是一个非常真实的漏洞我亲眼见过人们对此十分敏感。
请不要使用随机在 Google 上搜索的教程,因为其中 90% 都是垃圾,而是去阅读维基百科。真正了解您正在使用的网络服务器可能会很麻烦,但另一种情况是您的服务器受到攻击。