之前的工作中有遇到过nginx+php的环境新做的网站无法访问,各种出错的情况,往往是单一入口并且用了一些框架的架构。早期的nginx不支持pathinfo,只能通过正则之类的操作,辅以php.ini中cgi.fix_pathinfo,。后来又了解到了这样做可能会产生漏洞,如这篇文章描述的Nginx + PHP CGI的一个可能的安全漏洞。现在较新版本的nginx已经处理好这个问题了,只要适当配置,不会有什么问题。

fastcgi.conf可以这样写:

location ~ \.php {
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_param  PATH_INFO          $fastcgi_path_info;
        #fastcgi_param  PATH_TRANSLATED    $document_root$fastcgi_path_info;

        fastcgi_param  SCRIPT_FILENAME    $document_root$fastcgi_script_name;
        fastcgi_param  QUERY_STRING       $query_string;
        fastcgi_param  REQUEST_METHOD     $request_method;
        fastcgi_param  CONTENT_TYPE       $content_type;
        fastcgi_param  CONTENT_LENGTH     $content_length;

        fastcgi_param  SCRIPT_NAME        $fastcgi_script_name;
        fastcgi_param  REQUEST_URI        $request_uri;
        fastcgi_param  DOCUMENT_URI       $document_uri;
        fastcgi_param  DOCUMENT_ROOT      $document_root;
        fastcgi_param  SERVER_PROTOCOL    $server_protocol;
        fastcgi_param  HTTPS              $https if_not_empty;

        fastcgi_param  GATEWAY_INTERFACE  CGI/1.1;
        fastcgi_param  SERVER_SOFTWARE    nginx;

        fastcgi_param  REMOTE_ADDR        $remote_addr;
        fastcgi_param  REMOTE_PORT        $remote_port;
        fastcgi_param  SERVER_ADDR        $server_addr;
        fastcgi_param  SERVER_PORT        $server_port;
        fastcgi_param  SERVER_NAME        $server_name;

        # PHP only, required if PHP was built with --enable-force-cgi-redirect
        fastcgi_param  REDIRECT_STATUS    200;
        #fastcgi_pass   127.0.0.1:9000;
        fastcgi_pass   unix:/dev/shm/php-fpm.socket;
        fastcgi_index  index.php;
}

这样可以在nginx.conf的server段中直接include它。这个配置文件的重点在fastcgi_split_path_info上,能够处理PATHINFO信息,再通过fastcgi_param设置到位,这样在php当中就能够得到PATHINFO而进行解析。有些朋友使用的是fastcgi_params文件,同样也可以在其前部加入这两句话,效果一样。

这样做之后可以在php.ini中去掉cgi.fix_pathinfo前面的注释,并设置其值为0。PHP默认是启用的,注释的话也是使用默认的启用。避免漏洞,最好关掉。