PHP里經(jīng)常要獲取當(dāng)前請(qǐng)求的URL路徑信息。一般可以通過(guò)環(huán)境變量$_SERVER[‘PATH_INFO’]獲取,而配置文件中的cgi.fix_pathinifo選項(xiàng)則與這個(gè)值的獲取相關(guān)。而$_SERVER[‘PATH_INFO’]中的key PATH_INFO是一個(gè)CGI 1.1的標(biāo)準(zhǔn),經(jīng)常用來(lái)做為傳遞參數(shù)給后端的CGI服務(wù)器。
被很多系統(tǒng)用來(lái)優(yōu)化url路徑格式,比如對(duì)于很多框架,下面這個(gè)網(wǎng)址:
http://www.test.com/index.php/test/my.html?c=index&m=search
我們可以得到
$_SERVER[‘PATH_INFO’] = ‘/test/my.html’
$_SERVER[‘QUERY_STRING’] = ‘c=index&m=search’;
我們?cè)僬f(shuō)下php.ini中的配置參數(shù)cgi.fix_pathinfo,它是用來(lái)對(duì)設(shè)置cgi模式下為php是否提供絕對(duì)路徑信息或PATH_INFO信息。沒(méi)有這個(gè)參數(shù)之前PHP設(shè)置絕對(duì)路徑PATH_TRANSLATED的值為SCRIPT_FILENAME,沒(méi)有PATH_INFO值。設(shè)置cgi.fix_pathinfo=1后,cgi設(shè)置完整的路徑信息PATH_TRANSLATED的值為SCRIPT_FILENAME,并且設(shè)置PATH_INFO信息;如果設(shè)為cgi.fix_pathinfo=0則只設(shè)置絕對(duì)路徑PATH_TRANSLATED的值為SCRIPT_FILENAME。cgi.fix_pathinfo的默認(rèn)值是1。
nginx默認(rèn)是不會(huì)設(shè)置PATH_INFO環(huán)境變量的的值,需要通過(guò)正則匹配設(shè)置SCRIPT_FILENAME,但這樣會(huì)帶來(lái)安全隱患,需要把cgi.fix_pathinfo=0設(shè)置為0。但是一旦關(guān)閉這個(gè)這場(chǎng),PHP就獲取不到PATH_INFO信息,那些依賴PATH_INFO進(jìn)行URL美化的程序就失效了。
關(guān)于安全隱患的問(wèn)題,請(qǐng)看 http://www.laruence.com/2010/05/20/1495.html
網(wǎng)上給出了一些方案,在關(guān)閉cgi.fix_pathinfo時(shí)使依賴PATH_INFO美化url的程序能夠正常工作。
1.可以通過(guò)rewrite方式代替php中的PATH_INFO
實(shí)例:thinkphp的pathinfo解決方案
設(shè)置URL_MODEL=2
location / {
if (!-e $request_filename){
rewrite ^/(.*)$ /index.php?s=/$1 last;
}
}
2.nginx配置文件中設(shè)置PATH_INFO值
請(qǐng)求的網(wǎng)址是/abc/index.php/abc
PATH_INFO的值是/abc
SCRIPT_FILENAME的值是$doucment_root/abc/index.php
SCRIPT_NAME /abc/index.php
舊版本的nginx使用如下方式配置
location ~ .php($|/) {
set $script $uri;
set $path_info “”;
if ($uri ~ “^(.+.php)(/.+)”) {
set $script $1;
set $path_info $2;
}
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$script;
fastcgi_param SCRIPT_NAME $script;
fastcgi_param PATH_INFO $path_info;
}
新版本的nginx也可以使用fastcgi_split_path_info指令來(lái)設(shè)置PATH_INFO,舊的方式不再推薦使用,在location段添加如下配置。
location ~ ^.+.php {
…
fastcgi_split_path_info ^((?U).+.php)(/?.+)$;
fastcgi_param SCRIPT_FILENAME /path/to/php$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_param PATH_TRANSLATED $document_root$fastcgi_path_info;
…
}
通過(guò)上面的描述,我們似乎得出了一個(gè)結(jié)論:為了安全要關(guān)閉掉cgi.fix_pathinfo設(shè)置。
但是我們來(lái)看看php.ini的配置及說(shuō)明
; cgi.fix_pathinfo provides real PATH_INFO/PATH_TRANSLATED support for CGI. PHP’s
; previous behaviour was to set PATH_TRANSLATED to SCRIPT_FILENAME, and to not grok
; what PATH_INFO is. For more information on PATH_INFO, see the cgi specs. Setting
; this to 1 will cause PHP CGI to fix its paths to conform to the spec. A setting
; of zero causes PHP to behave as before. Default is 1. You should fix your scripts
; to use SCRIPT_FILENAME rather than PATH_TRANSLATED.
; http://php.net/cgi.fix-pathinfo
cgi.fix_pathinfo=1
設(shè)置cgi.fix_pathinfo=1才符合cgi標(biāo)準(zhǔn)。那么有什么辦法可以在保持cgi.fx_pathinfo默認(rèn)設(shè)置的情況下,保證系統(tǒng)安全嗎?
好消息,新版本PHP(我驗(yàn)證至少PHP5已經(jīng)有了這個(gè)參數(shù))的fpm配置里新增了一個(gè)額外參數(shù)(php-fpm.d/www.conf),
security.limit_extensions = .php .php3 .php4 .php5 .php7
專門用來(lái)限制PHP腳本引擎只支持解析哪些擴(kuò)展名的文件
; Limits the extensions of the main script FPM will allow to parse. This can
; prevent configuration mistakes on the web server side. You should only limit
; FPM to .php extensions to prevent malicious users to use other extensions to
; execute php code.
; Note: set an empty value to allow all extensions.
; Default Value: .php
;security.limit_extensions = .php .php3 .php4 .php5 .php7
所以在使用nginx+php-fpm時(shí),可以不用修改系統(tǒng)默認(rèn)的cgi. fix_pathinfo=1設(shè)置了。
References:
http://www.laruence.com/2010/05/20/1495.html