Nginx(PHP/fastcgi)的PATH_INFO配置

PS:Nginx(PHP/fastcgi)的PATHINFO配置
PATHINFO是一个CGI 1.1的标准,经常用来做为传参载体,在Apache中, 当不加配置的时候, 对于PHP脚本, AcceptPathInfo是默认接受的,而对于Nginx下, 是不支持PATHINFO 的, 也就是需要设置才能使用PATHINFO模式.
我们可以使用PATH_INFO来代替Rewrite来实现伪静态页面, 很多PHP框架也使用PATHINFO模式来作为路由载体

  1. Apache 默认设置PATHINFO原理分析
    • 对于请求http://wangying.sinaapp.com/tools/index.php/login/index
      或对于请求http://wangying.sinaapp.com/tools/login/index
      只要服务器在存在一个/tools/index.php
      Apache都接受, 都会认为是对index.php的访问, 并会设置PATH_INFO为’/login/index’

                  print_r($_SERVER["PATH_INFO"]);//login/index
                  
  2. nginx 解析文件原理分析

    • Nginx是通过对文件名的扩展名匹配,来决定是否要交给php cgi服务器去解释的.在nginx.conf中一般都有如下的默认配置段:

                      location ~ .php$ {
                           fastcgi_index index.php;
                           fastcgi_pass 127.0.0.1:9000;
                           include fastcgi_params;
                      }
                      
    • 对于形如tools/index.php/login/index这样的文件路径, Nginx正则匹配的是url路径而不是php文件. 所以我们需要去掉($)改写这段配置匹配带有php的扩展名:

                      location ~ .php {
                           fastcgi_index index.php;
                           fastcgi_pass 127.0.0.1:9000;
                           include fastcgi_params;
                      }
                      
    • 现在, 脚本路径已经交由PHP自己处理了. 那怎么增加PATH_INFO呢?
      方案一:php内置解析
      我们需要打开PHP中cgi.fix_pathinfo配置项, 打开这个配置项以后, PHP会去根据CGI规范来检查SCRIPT_FILENAME中那部分是访问脚本和PATH_INFO(ini配置解释), 并根据SCRIPT_NAME来修改PATH_INFO(和PATH_TRANSLATED)为正确的值然后, 就只要添加一个FASTCGI_PARAM项就好了:

                  location ~ .php {
                       fastcgi_index index.php;
                       fastcgi_pass 127.0.0.1:9000;
                       include fastcgi_params;
                       fastcgi_param PATH_INFO $fastcgi_script_name;
                  }
                  

      注意:php.ini默认是开启的fix_pathinfo=1 会导致一个非常严重的《nginx文件类型错误解析漏洞》bug,服务器配置过程中一定要关闭fix_pathinfo
      方案二:nginx正则解析
      上面的解决方法把对路径的分析交给了PHP去处理具有严重bug,最安全的还是由Nginx来分析路径(摒弃掉fix_pathinfo),两种配置方案

                  #配置方案 使用nginx模块fastcgi_split_path_info(nginx版本>0.7.31)
                  location ~ \.php {
                      fastcgi_pass   127.0.0.1:9000;
                      fastcgi_index  index.php;
                      #先加载默认后解析赋值
                      include        fastcgi_params;
                      #正则解析路径
                      fastcgi_split_path_info ^((?U).+\.php)(/?.+)$;
                      fastcgi_param  PATH_INFO        $fastcgi_path_info;
                      fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
                  }
                  

                      /*
                      fastcgi_split_path_info
                      语法:fastcgi_split_path_info regex
                      使用字段:location
                      可用版本:0.7.31以上
                      这个指令允许为CGI specification设置SCRIPT_FILENAME、SCRIPT_NAME、PATH_INFO变量。正则包含两个组:
                      处理请求的脚本路径–>对应$fastcgi_script_name
                      脚本参数的值–>      对应$fastcgi_path_info
                      */
                      location ~ ^.+\.php {
                      (...)
                      fastcgi_split_path_info ^((?U).+\.php)(/?.+)$;
                      fastcgi_param PATH_INFO       $fastcgi_path_info;
                      fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
                      fastcgi_param PATH_TRANSLATED $document_root$fastcgi_path_info;
                      (...)
                      }
                      /*
                      示例请求”/show.php/article/0001”的参数SCRIPT_FILENAME将设置为”/path/to/php/show.php”,参数PATH_INFO为”/article/0001”*/
                      

                      #配置方案2
                      #由于nginx内建只读变量$fastcgi_script_name无法赋值,所有通过设置$real_script_name变量来做中间值
                      location ~ \.php {
                          fastcgi_pass   127.0.0.1:9000;
                          fastcgi_index  index.php;
                          #先加载默认后解析赋值
                          include        fastcgi_params;
                          #正则解析路径
                          set $path_info "";
                          set $real_script_name $fastcgi_script_name;
                          if ($fastcgi_script_name ~ "^(.+?\.php)(/.+)$") {
                              set $real_script_name $1;
                              set $path_info $2;
                          }
                          fastcgi_param PATH_INFO       $path_info;
                          fastcgi_param SCRIPT_FILENAME $document_root$real_script_name;
                          fastcgi_param SCRIPT_NAME     $real_script_name;
                      }
                  
                      /*nginx 把nginx解析url变量赋值给fastcgi_param,php通过$_SERVER获取fastcgi_param中的所有变量值 */
                      Array
                      (
                          [USER] => www
                          [HOME] => /home/www
                          [FCGI_ROLE] => RESPONDER
                          [QUERY_STRING] =>
                          [REQUEST_METHOD] => GET
                          [CONTENT_TYPE] =>
                          [CONTENT_LENGTH] =>
                          [SCRIPT_NAME] => /demos/doitnote/index.php    //重点关注
                          [REQUEST_URI] => /demos/doitnote/index.php/login/index
                          [DOCUMENT_URI] => /demos/doitnote/index.php/login/index
                          [DOCUMENT_ROOT] => /mnt/hgfs/vmhtml/doitphp
                          [SERVER_PROTOCOL] => HTTP/1.1
                          [GATEWAY_INTERFACE] => CGI/1.1
                          [SERVER_SOFTWARE] => nginx/1.1.19
                          [REMOTE_ADDR] => 192.168.127.1
                          [REMOTE_PORT] => 60422
                          [SERVER_ADDR] => 192.168.127.10
                          [SERVER_PORT] => 80
                          [SERVER_NAME] => www.doitphp.loc
                          [REDIRECT_STATUS] => 200
                          [PATH_INFO] => /login/index  //重点关注
                          [SCRIPT_FILENAME] => /mnt/hgfs/vmhtml/doitphp/demos/doitnote/index.php  //重点关注
                          [HTTP_HOST] => www.doitphp.loc
                          [HTTP_USER_AGENT] => Mozilla/5.0 (Windows NT 6.1; rv:16.0) Gecko/20100101 Firefox/16.0
                          [HTTP_ACCEPT] => text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
                          [HTTP_ACCEPT_LANGUAGE] => zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3
                          [HTTP_ACCEPT_ENCODING] => gzip, deflate
                          [HTTP_CONNECTION] => keep-alive
                          [HTTP_REFERER] => http://www.doitphp.loc/demos/doitnote/
                          [HTTP_CACHE_CONTROL] => max-age=0
                          [PHP_SELF] => /demos/doitnote/index.php/login/index
                          [REQUEST_TIME] => 1354246274
                      )
                      
相关文章
  1. php-redis扩展
  2. Gearman-PHP扩展源码编译
  3. Zend Opcache 加速 PHP
  4. php安装memcached扩展
  5. php下添加pdo_mysql扩展
  6. Nginx使用的php-fpm的两种进程管理方式及优化
本站版权
1、本站所有主题由该文章作者发表,该文章作者与尘埃享有文章相关版权
2、其他单位或个人使用、转载或引用本文时必须同时征得该文章作者和尘埃的同意
3、本帖部分内容转载自其它媒体,但并不代表本站赞同其观点和对其真实性负责
4、如本帖侵犯到任何版权问题,请立即告知本站,本站将及时予与删除并致以最深的歉意
5、原文链接:
二维码
Posted in lnmp源码安装, Nginx, php, web服务器, 编程语言
Comments are closed.