Nginx、PATH_INFO 和 url 重寫:我一定遺漏了一些東西
我正在從 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; } }
使用“ 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"
但是,它似乎正在尋找目錄“test”。如何強制它請求 index.php,將“/test”傳遞給腳本?
看起來您正在學習一個嚴重過時的糟糕教程(
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% 完全是垃圾,而是去閱讀wiki。實際了解您正在使用的 Web 伺服器可能會很麻煩,但另一種方法是讓您的伺服器受到損害。