Nginx的,PATH_INFO,和URL重写:我必须缺less的东西

我正在从Apache切换到Nginx / fcgi,而且在尝试设置应用程序重写规则时遇到小问题。

代码通过使用PATH_INFO来处理路由,例如example.com/foo/bar/将被路由到example.com/index.php/foo/bar/

我已经修改了服务器configuration来传递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; } } 

有了' rewrite_log on ',这个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" 

但是,它似乎在寻找目录“testing”。 我如何强制它请求index.php,传递'/testing'的脚本?

那么你有很多问题,首先你要遵循严重过时的低劣教程。 if (!-f通常不推荐使用try_files作为更好的替代品。

其次,在位置/上下文中应该在服务器上下文中有指令,这样可以避免SCRIPT_FILENAMEvariables中的path重复。

其次,在重写中使用break标志,这意味着它不应该重新评估位置匹配。 这实际上使请求永远不会离开位置/块,而是被当作一个静态文件请求。

第三。 看看你的location ~ \.php$ {

Nginx匹配URI的位置,你特别告诉Nginx只处理以.php结尾的URI,但是如果你重写了index.php / test /那么它将不会触发。

最后。 您正在使用PATH_INFO,而您应该使用REQUEST_URI。 不同之处在于要使PATH_INFO正常工作,您必须告诉Nginx将任何带.php的请求传递给PHP,然后PHP必须find正确的文件。

这意味着你允许像example.org/uploads/image.jpg/index.php这样的请求被发送到PHP,你也允许PHP执行文件/uploads/image.jpg。 如果恶意用户用PHP上传了这个文件,他们现在在你的服务器上执行任意代码。 这是我亲眼所见的一个非常真实的利用。

请停止使用随机谷歌教程,因为其中90%是完全垃圾,而不是去阅读维基 。 这可能是一个麻烦,不得不实际了解您使用的Web服务器,但另一种方法是让您的服务器妥协。