理解和实施的FastCGI代理功能中的Nginx

Nginx的已经成为了最灵活和强大的Web服务器解决方案之一。然而,在设计方面,它首先是一个代理服务器。这种专注意味着,Nginx的工作来处理与其他服务器的请求时,是非常高性能的。 Nginx的可以代理...

介绍

Nginx已经成为最灵活和功能最强大的Web服务器解决方案之一。 然而,在设计方面,它首先是一个代理服务器。 这个焦点意味着Nginx在处理与其他服务器的请求时非常有效。

Nginx可以使用http,FastCGI,uwsgi,SCGI或memcached代理请求。 在本指南中,我们将讨论FastCGI代理,这是最常见的代理协议之一。

为什么要使用FastCGI代理?

Nginx中的FastCGI代理通常用于转换不直接处理客户端请求或不应该直接处理客户端请求的应用程序服务器的客户端请求。 FastCGI是基于早期CGI或通用网关接口的协议,旨在通过不将每个请求作为单独的进程来运行来提高性能。 它用于与处理动态内容请求的服务器有效地接口。

Nginx中FastCGI代理的主要用例之一是用于PHP处理。 不同于Apache的,它可以与使用的直接处理PHP处理mod_php模块,Nginx的必须依赖于一个单独的PHP处理器来处理PHP请求。 大多数情况下,这种处理与处理php-fpm ,已被广泛的测试与Nginx的工作一个PHP处理器。

具有FastCGI的Nginx可以与使用其他语言的应用程序一起使用,只要存在配置为响应FastCGI请求的可访问组件。

FastCGI代理基础

一般来说,代理请求涉及代理服务器,在这种情况下Nginx将客户端请求转发到后端服务器。 这Nginx的使用实际的服务器代理定义使用FastCGI协议的指令是fastcgi_pass

例如,要将任何匹配的PHP请求转发给使用FastCGI协议处理PHP处理的后端,基本位置块可能如下所示:

# server context

location ~ \.php$ {
    fastcgi_pass 127.0.0.1:9000;
}

. . .

上面的代码段实际上不会开箱即用,因为它提供的信息太少。 无论何时进行代理连接,都必须转换原始请求,以确保代理请求对后端服务器有意义。 由于我们使用FastCGI传递来改变协议,这需要一些额外的工作。

虽然http-to-http代理主要涉及增加http头以确保后端具有代表客户端响应代理服务器所需的信息,FastCGI是一个单独的协议,不能读取http头。 由于这种考虑,任何相关信息必须通过其他方式传递到后端。

使用FastCGI协议时传递额外信息的主要方法是使用参数。 应该配置后台服务器以读取和处理这些,根据发现的情况修改其行为。 Nginx的可以使用FastCGI的设置参数fastcgi_param指令。

在PHP的FastCGI代理场景中实际工作的最小配置是这样的:

# server context

location ~ \.php$ {
    fastcgi_param REQUEST_METHOD $request_method;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    fastcgi_pass 127.0.0.1:9000;
}

. . .

在上述结构中,我们设置两个FastCGI的参数,称为REQUEST_METHODSCRIPT_FILENAME 这些都是为了让后端服务器了解请求的性质所必需的。 前者告诉它应该执行什么类型的操作,而后者告诉上游哪个文件要执行。

在示例中,我们使用一些Nginx变量来设置这些参数的值。 $request_method变量将总是包含由客户端请求的HTTP方法。

SCRIPT_FILENAME参数设置为所述的组合$document_root变量和$fastcgi_script_name变量。 $document_root将包含路径的基本目录,由设置root指令。 $fastcgi_script_name变量将被设置为请求URI。 如果请求URI以斜杠(/)结束时,值fastcgi_index指令将被追加到结束。 这种类型的自引用位置定义是可能的,因为我们在与我们的Nginx实例相同的机器上运行FastCGI处理器。

让我们看另一个例子:

# server context
root /var/www/html;

location /scripts {
    fastcgi_param REQUEST_METHOD $request_method;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    fastcgi_index index.php;
    fastcgi_pass unix:/var/run/php5-fpm.sock;
}

. . .

如果上面的位置被选择以处理一个请求/scripts/test/时,的值SCRIPT_FILENAME将成为的值的组合root指令,请求URI和fastcgi_index指令。 在这个例子中,参数将被设置为/var/www/html/scripts/test/index.php

我们在上面的配置中做了另一个重大变化,因为我们使用Unix套接字而不是网络套接字指定了FastCGI后端。 Nginx可以使用任一类型的接口连接到FastCGI上游。 如果FastCGI处理器位于同一主机上,为了安全起见,建议使用Unix套接字。

分解FastCGI配置

可维护代码的一个关键规则是尝试遵循DRY(“Do not Repeat Yourself”)原则。 这有助于减少错误,增加可重用性,并允许更好的组织。 考虑到管理Nginx的核心建议之一是始终将指令设置在其最广泛的适用范围,这些基本目标也适用于Nginx配置。

当处理FastCGI代理配置时,大多数使用实例将共享大部分配置。 由于这一点,并且由于Nginx继承模型的工作方式,在一般范围中声明参数几乎总是有利的。

在父上下文中声明FastCGI配置详细信息

减少重复的一种方法是在较高的父上下文中声明配置细节。 实际的以外的所有参数fastcgi_pass可以在更高的水平进行指定。 它们将向下级联到传球发生的位置。 这意味着多个位置可以使用相同的配置。

例如,我们可以修改上一节中的最后一个配置片段,使其在多个位置有用:

# server context
root /var/www/html;

fastcgi_param REQUEST_METHOD $request_method;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_index index.php;

location /scripts {
    fastcgi_pass unix:/var/run/php5-fpm.sock;
}

location ~ \.php$ {
    fastcgi_pass 127.0.0.1:9000;
}

. . .

在上面的例子中,两个的fastcgi_param声明和fastcgi_index指令是在两个而来后位置的块提供。 这是删除重复声明的一种方法。

然而,上述构造具有一个严重的缺点。 如果任何fastcgi_param在下部上下文中声明, 没有任何fastcgi_param从父上下文值将被继承。 你要么使用继承的值,或者你用没有。

fastcgi_param指令是Nginx的中说法数组指令。 从用户的角度来看,数组指令基本上是在单个上下文中可以多次使用的任何指令。 每个后续的声明将附加新的信息到Nginx从以前的声明知道。 fastcgi_param指令是为了允许用户设置多个参数设计成一个阵列指令。

Array指令以不同于某些其他指令的方式继承到子上下文。 从阵列指令中的信息将继承到子上下文只有当它们不存在在孩子方面的任何地方 这意味着,如果你使用fastcgi_param您的位置内,它将有效地清除了从完全的父上下文继承的值。

例如,我们可以稍微修改以上配置:

# server context
root /var/www/html;

fastcgi_param REQUEST_METHOD $request_method;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_index index.php;

location /scripts {
    fastcgi_pass unix:/var/run/php5-fpm.sock;
}

location ~ \.php$ {
    fastcgi_param QUERY_STRING $query_string;
    fastcgi_pass 127.0.0.1:9000;
}

. . .

乍一看,你可能认为REQUEST_METHODSCRIPT_FILENAME参数将被继承到第二位置的块,用QUERY_STRING参数是另外可用于特定的上下文。

实际发生的事情是, 所有的父母fastcgi_param值在第二范围内被消灭,只有QUERY_STRING参数设置。 REQUEST_METHODSCRIPT_FILENAME参数将保持未设置状态。

有关同一上下文中参数的多个值的注释

在这一点上绝对值得一提的一件事是在单个上下文中为相同参数设置多个值的含义。 让我们以下面的例子作为讨论点:

# server context

location ~ \.php$ {
    fastcgi_param REQUEST_METHOD $request_method;
    fastcgi_param SCRIPT_FILENAME $request_uri;

    fastcgi_param DOCUMENT_ROOT initial;
    fastcgi_param DOCUMENT_ROOT override;

    fastcgi_param TEST one;
    fastcgi_param TEST two;
    fastcgi_param TEST three;

    fastcgi_pass 127.0.0.1:9000;
}

. . .

在上面的例子中,我们确定的TESTDOCUMENT_ROOT参数单一上下文内多次。 由于fastcgi_param是一个数组的指令,每个后续声明添加到Nginx的内部资料。 TEST参数将数组其设置为在声明onetwo ,和three

在这一点上重要的是,所有这些将被传递到FastCGI后端,而不需要任何进一步的处理从Nginx。 这意味着完全取决于选择的FastCGI处理器来决定如何处理这些值。 不幸的是,不同的FastCGI处理器处理传递的价值观完全不同

例如,如果上述参数由PHP-FPM接收时, 最终值将被解释为覆盖任何以前的值。 所以在这种情况下, TEST参数将被设置为three 同样, DOCUMENT_ROOT参数将被设置为override

但是,如果将上述值传递给类似FsgiWrap的值,则值的解释方式大不相同。 首先,它通过初始传递来决定使用哪些值来运行脚本。 它将使用DOCUMENT_ROOT的值, initial去寻找脚本。 但是,当它将实际参数传递给脚本时,它将传递最终的值,就像PHP-FPM一样。

这种不一致和不可预测性意味着您不能也不应该依赖后端在多次设置相同参数时正确解释您的意图。 唯一安全的解决方案是只声明每个参数一次。 这也意味着,有没有这样的东西作为安全压倒一切的默认值fastcgi_param指令。

使用包含从单独的文件中源FastCGI配置

还有另一种方法来分离出您的常见配置项。 我们可以使用include指令在一个单独的文件中的指令声明的位置的内容阅读。

这意味着我们可以将所有常见配置项保存在一个文件中,并将其包含在我们需要它的配置中的任何位置。 由于Nginx的将会把实际的文件内容,其中include被调用时,我们不会从一个孩子在一个父上下文继承向下。 这将防止fastcgi_param被歼灭,使我们能够设置其他参数为必要的值。

首先,我们可以在配置目录中的一个单独的文件中设置我们常用的FastCGI配置值。 我们称这个文件fastcgi_common

fastcgi_param REQUEST_METHOD $request_method;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;

现在,我们可以在这个文件中读取我们希望使用那些配置值:

# server context
root /var/www/html;

location /scripts {
    include fastcgi_common;

    fastcgi_index index.php;
    fastcgi_pass unix:/var/run/php5-fpm.sock;
}

location ~ \.php$ {
    include fastcgi_common;
    fastcgi_param QUERY_STRING $query_string;
    fastcgi_param CONTENT_TYPE $content_type;
    fastcgi_param CONTENT_LENGTH $content_length;

    fastcgi_index index.php;
    fastcgi_pass 127.0.0.1:9000;
}

. . .

在这里,我们提出一些共同fastcgi_param值一个名为fastcgi_common在我们的默认Nginx的配置目录。 然后,当我们要插入在其中声明的值时,我们会导出该文件。

有关此配置的一些注意事项。

第一件事是,我们没有在我们计划提供的文件中放置任何我们希望在每个位置的基础上定制的值。 因为上面提到的解释的问题,当为同一个参数设置多个值时,并且因为非数组指令只能在每个上下文中设置一次,所以只有将不想更改的公共文件放在项目中。 我们可能希望在每个上下文的基础上定制的每个指令(或参数键)应该不在公共文件中。

您可能已经注意到的另一件事是,我们在第二个位置块中设置一些额外的FastCGI参数。 这是我们希望实现的能力。 我们可以设置其他fastcgi_param参数,而且不会消灭的共同价值观。

使用fastcgi_params文件或fastcgi.conf文件

考虑到上述策略,Nginx开发人员和许多分发包装团队一直致力于提供一系列通用参数,您可以将这些参数包含在FastCGI传递位置中。 这些被称为fastcgi_paramsfastcgi.conf

这两个文件大部分是相同的,唯一的区别实际上是我们前面讨论的为单个参数传递多个值的问题的结果。 fastcgi_params文件不包含在一项声明SCRIPT_FILENAME参数,而fastcgi.conf文件一样。

fastcgi_params文件已可使用的时间更长的时间。 为了避免依赖于打破配置fastcgi_params ,当决定做出提供一个默认值SCRIPT_FILENAME ,需要创建一个新的文件。 不这样做可能导致在通用文件和FastCGI传递位置中设置该参数。 这是非常详细描述马丁Fjordvald出色的岗位上这两个文件的历史记录

许多流行发行版的软件包维护者选择只包含其中一个文件或者完全镜像它们的内容。 如果您只有其中一个可用,请使用您有一个。 随意修改它,以适应你的需要。

如果您同时提供给你这些文件,对于大多数的FastCGI通过的地方,也可能是更好的包括fastcgi.conf文件,因为它包括了一个声明SCRIPT_FILENAME参数。 这通常是可取的,但在某些情况下,您可能希望自定义此值。

这些可以通过引用它们相对于根Nginx配置目录的位置来包括。 根Nginx的配置目录通常是这样/etc/nginx时候Nginx的已安装的软件包管理器。

您可以包括这样的文件:

# server context

location ~ \.php$ {
    include fastcgi_params;
    # You would use "fastcgi_param SCRIPT_FILENAME . . ." here afterwards

    . . .

}

或者像这样:

# server context

location ~ \.php$ {
    include fastcgi.conf;

    . . .

}

重要FastCGI指令,参数和变量

在上面的部分中,我们设置了相当多的参数,通常是Nginx变量,作为展示其他概念的一种方法。 我们还引入了一些FastCGI指令,而没有太多的解释。 在本节中,我们将讨论一些常见的设置参数,可能需要修改的参数,以及可能包含所需信息的一些变量。

常见FastCGI指令

下面列出了使用FastCGI传递的一些最有用的指令:

  • fastcgi_pass :传递在目前情况下对后端请求的实际指令。 这定义了可以到达FastCGI处理器的位置。
  • fastcgi_param :可用于参数设定值的阵列指令。 通常,这与Nginx变量一起使用,以将FastCGI参数设置为特定于请求的值。
  • try_files :没有特定的FastCGI的指导性,但通过FastCGI的位置内使用的通用指令。 这通常用作请求卫生例程的一部分,以确保在将请求文件传递到FastCGI处理器之前存在所请求的文件。
  • include :同样,没有一个具体的FastCGI-指令,而是一个相当沉重的用法在FastCGI的通上下文。 通常,这用于在多个位置包括常见的共享配置详细信息。
  • fastcgi_split_path_info :这个指令定义包含两个捕获组正则表达式。 第一捕获组被用作所述的价值$fastcgi_script_name变量。 所述第二捕获组被用作所述的价值$fastcgi_path_info变量。 这两个都经常用于正确解析请求,以便处理器知道请求的哪些片段是要运行的文件,哪些部分是传递给脚本的附加信息。
  • fastcgi_index :这个定义应该追加到索引文件$fastcgi_script_name值以斜杠(完/ )。 如果这往往是有用SCRIPT_FILENAME参数设置为$document_root$fastcgi_script_name和位置的块被配置为接受与该文件后的信息的请求。
  • fastcgi_intercept_errors :这个指令定义是否从FastCGI的服务器接收到的错误应该由Nginx的或处理直接传递到客户端。

上述指令代表了在设计典型的FastCGI传递时将使用的大部分内容。 你可能不会一直使用所有这些,但我们可以开始看到,他们与FastCGI参数和变量非常密切,我们将在下面讨论。

与FastCGI一起使用的常见变量

在我们谈论你可能使用FastCGI传递的参数之前,我们应该谈一些常见的Nginx变量,我们将在设置这些参数时利用它们。 其中一些由Nginx的FastCGI模块定义,但大多数来自Core模块。

  • $query_string$args :在原有的客户端请求给出的参数。
  • $is_args :将等于“?” 如果请求中有参数,并且将被设置为空字符串,否则。 这在构造可能有或没有参数的参数时很有用。
  • $request_method :这表明原始客户端请求的方法。 这在确定在当前上下文中是否应该允许操作时是有用的。
  • $content_type :此设置为Content-Type请求头。 如果用户的请求是POST,以便正确处理后续内容,代理需要此信息。
  • $content_length :这被设置为的值Content-Length从客户端头。 任何客户端POST请求都需要此信息。
  • $fastcgi_script_name :这将包含在脚本文件来运行。 如果请求以斜线(/)结束时,值fastcgi_index指令将被追加到结束。 在该事件fastcgi_split_path_info指令时,该变量将被设置到由该指令定义的第一捕获基。 此变量的值应指示要运行的实际脚本。
  • $request_filename :这个变量将包含请求的文件的文件路径。 它通过利用当前文档根值,同时考虑到在得到这个值rootalias指令以及价值$fastcgi_script_name 这是分配的非常灵活的方式SCRIPT_FILENAME参数。
  • $request_uri :从客户端接收整个请求。 这包括脚本,任何其他路径信息,以及任何查询字符串。
  • $fastcgi_path_info :此变量包含在请求中的脚本名称后其他可用的路径信息。 此值有时包含另一个要执行的脚本应该知道的位置。 该变量使用时,从第二捕获正则表达式组获取其值fastcgi_split_path_info指令。
  • $document_root :此变量包含当前文档根值。 这将根据设置rootalias指令。
  • $uri :此变量包含当前URI与应用正常化。 由于某些重写或内部重定向的指令可能会对URI产生影响,因此该变量将表示这些更改。

如您所见,在决定如何设置FastCGI参数时,有很多变量可供使用。 其中许多是类似的,但有一些细微的差异,将影响您的脚本的执行。

常用FastCGI参数

FastCGI参数表示我们希望提供给我们发送请求的FastCGI处理器的键值信息。 不是每个应用程序都需要相同的参数,因此您经常需要查阅应用程序的文档。

这些参数中的一些是处理器正确地识别要运行的脚本所必需的。 其他可用于脚本,如果配置为依赖于设置的参数,可能修改其行为。

  • QUERY_STRING :这个参数应当被设置为客户端提供任何查询字符串。 这通常是在“?”之后提供的键值对。 在URI中。 通常情况下,此参数设置为任一$query_string$args变量,这两者应该包含相同的数据。
  • REQUEST_METHOD :该参数表示这是由客户端所请求的动作的类型的FastCGI处理器。 这是为了使pass能够正确工作而需要设置的少数参数之一。
  • CONTENT_TYPE :如果上面设定的请求方法是“POST”,这一参数必须设置。 它指示FastCGI处理器应该期望的内容类型。 这是几乎永远只是设置为$content_type变量,它是根据原始请求信息集。
  • CONTENT_LENGTH :如果请求方法是“POST”,这一参数必须设置。 这表示内容长度。 这是几乎永远只是设置为$content_length ,从信息获取原始客户机请求其值的变量。
  • SCRIPT_NAME :此参数用于指示将要运行主脚本的名称。 这是一个非常重要的参数,可以根据您的需要以各种方式设置。 通常情况下,这是设置为$fastcgi_script_name ,这应该是请求URI,请求URI与fastcgi_index如果如果使用带斜线,还是先捕获组结束追加fastcgi_fix_path_info
  • SCRIPT_FILENAME :该参数指定的脚本运行在磁盘中的实际位置。 因为它关系到的SCRIPT_NAME参数,一些导游建议大家使用$document_root$fastcgi_script_name 具有许多优点的另一个替代方法是使用$request_filename
  • REQUEST_URI :这应该包含完整的,未经修改的请求的URI,完整的脚本运行,更多的路径信息,以及任何参数。 一些应用程序更喜欢自己解析这个信息。 此参数为他们提供了必要的信息。
  • PATH_INFO :如果cgi.fix_pathinfo在PHP配置文件中设置为“1”,这将包含在脚本名称后添加任何额外的路径信息。 这通常用于定义脚本应该执行的文件参数。 设置cgi.fix_pathinfo为“1”可以有安全隐患,如果脚本请求不通过其他途径消毒(我们将讨论这个版本)。 有时这被设置为$fastcgi_path_info变量,它包含了从第二捕获组fastcgi_split_path_info指令。 其他时候,需要使用临时变量,因为该值有时被其他处理破坏。
  • PATH_TRANSLATED :此参数映射其中所包含的路径信息PATH_INFO为实际的文件系统路径。 通常,这将被设置为类似$document_root$fastcgi_path_info ,但有时后来变量必须通过临时保存变量代替如上所指出。

在传递到FastCGI之前检查请求

我们还没有介绍的一个非常重要的主题是如何安全地将动态请求传递到应用程序服务器。 将所有请求传递给后端应用程序,不管其有效性,不仅效率低下,而且危险。 攻击者可能制造恶意请求,试图让您的服务器运行任意代码。

为了解决这个问题,我们应该确保我们只向FastCGI处理器发送合法请求。 我们可以根据特定设置的需要以及FastCGI处理器是否与我们的Nginx实例位于同一系统上以多种方式做到这一点。

应该告诉我们如何设计我们的配置的一个基本规则是,我们不应该允许任何处理和解释用户文件。 恶意用户相对容易将有效的代码嵌入看似无害的文件(例如图像)中。 一旦这样的文件上传到我们的服务器,我们必须确保它从来没有到我们的FastCGI处理器。

我们试图解决的主要问题是在CGI规范中实际指定的问题。 规范允许您指定要运行的脚本文件,后面是脚本可以使用的其他路径信息。 这种执行模式允许用户请求可能看起来像合法脚本的URI,而将被执行的实际部分将在路径中较早。

考虑请求/test.jpg/index.php 如果您的配置只是简单地传递结束在每次请求.php到您的处理器没有测试它的合法性,处理器,如果按照规范,将检查该位置,如果可能执行它。 如果没有找到该文件,它将然后按照规范,试图执行/test.jpg文件,标志着/index.php作为脚本的附加路径信息。 您可以看到,这可能会导致一些非常不理想的后果,结合用户上传的想法。

有许多不同的方法来解决这个问题。 最简单的,如果你的应用程序不依赖这个额外的路径信息进行处理,就是简单地在处理器中关闭它。 对于PHP-FPM,您可以在您关闭这个功能php.ini文件。 例如,在Ubuntu系统上,您可以编辑此文件:

sudo nano /etc/php5/fpm/php.ini

简单搜索cgi.fix_pathinfo选项,取消它,将其设置为“0”,以禁用此“功能”:

cgi.fix_pathinfo=0

重新启动PHP-FPM进程以进行更改:

sudo service php5-fpm restart

这将导致PHP只尝试在路径的最后一个组件上执行。 因此,在我们上面的例子,如果/test.jpg/index.php文件不存在,PHP将正确错误而不是试图执行/test.jpg

另一个选项,如果我们的FastCGI处理器与我们的Nginx实例在同一台机器上,只是简单地检查磁盘上的文件的存在,然后将它们传递到处理器。 如果/test.jgp/index.php文件不存在,报错了。 如果是,则将其发送到后端进行处理。 这将在实践中导致大部分与我们上面相同的行为:

location ~ \.php$ {
        try_files $uri =404;

        . . .

}

如果的应用程序依赖于正确的解释路径信息的行为,你仍然可以放心地允许决定是否将请求发送给后端之前做检查这种行为。

例如,我们可以具体匹配允许不受信任上传的目录,并确保它们不会传递给我们的处理器。 举例来说,如果我们的应用程序的上传目录是/uploads/ ,我们可以创建一个这样的位置块的正则表达式求值之前匹配:

location ^~ /uploads {
}

在内部,我们可以禁用任何类型的PHP文件处理:

location ^~ /uploads {
    location ~* \.php$ { return 403; }
}

父位置将匹配任何请求,开始/uploads和PHP文件处理将返回403错误,而不是一起到后台发送它的任何请求。

你还可以使用fastcgi_split_path_info指令来手动定义应被解释为脚本,并且应该被定义为使用正则表达式的额外的路径信息的部分中的请求的部分。 这允许您仍然依赖于路径信息功能,但是确切地定义您认为脚本和您认为的路径。

例如,我们可以设置认为结尾的路径组件的第一个实例的位置块.php作为脚本运行。 其余的将被视为额外的路径信息。 这将意味着在一个请求的实例/test.jpg/index.php ,整个路径可以被发送到处理器为没有额外的路径信息的脚本名。

此位置可能如下所示:

location ~ [^/]\.php(/|$) {

    fastcgi_split_path_info ^(.+?\.php)(.*)$;
    set $orig_path $fastcgi_path_info;

    try_files $fastcgi_script_name =404;

    fastcgi_pass unix:/var/run/php5-fpm.sock;
    fastcgi_index index.php;
    include fastcgi_params;

    fastcgi_param SCRIPT_FILENAME $request_filename;
    fastcgi_param PATH_INFO $orig_path;
    fastcgi_param PATH_TRANSLATED $document_root$orig_path;
}

块以上的应PHP配置工作,在那里cgi.fix_pathinfo被设置为“1”,允许额外的路径信息。 在这里,我们的位置块不仅与最终请求相匹配.php ,而且那些.php只是表明一个额外的目录部分斜杠(/)如下之前。

块内部, fastcgi_split_path_info指令定义了两个捕获组,正则表达式。 第一组的URI的从开始部分相匹配的第一个实例.php并将,在$fastcgi_script_name变量。 然后,它会从该点的任何信息以后到第二捕获组,它存储在一个名为变量$fastcgi_path_info

我们用set指令存储在保存的值$fastcgi_path_info在这一点上到一个变量称为$orig_path 这是因为$fastcgi_path_info变量将在我们的一瞬间灰飞烟灭try_files指令。

我们的测试,我们使用上面拍摄的脚本名称try_files 这是一个文件操作,将确保我们试图运行的脚本在磁盘上。 然而,这也有清除的一个副作用$fastcgi_path_info变量。

做传统的FastCGI的传球之后,我们设置SCRIPT_FILENAME如常。 我们还设置PATH_INFO为我们卸载到价值$orig_path变量。 虽然我们的$fastcgi_path_info被清除,其原始值保留在这个变量。 我们还设置了PATH_TRANSLATED参数映射额外的路径信息,以它存在于磁盘上的位置。 我们通过合并为此$document_root变量与$orig_path变量。

这使我们能够建立类似的请求/index.php/users/view使我们/index.php文件可以处理有关信息/users/view目录,同时避免在那里的情况/test.jpg/index.php将会运行。 它总是将脚本设置为在截至最短组件.php ,从而避免这一问题。

如果我们需要更改脚本文件的位置,我们甚至可以使用别名指令。 我们只是在我们两个的位置头部和考虑到这一点fastcgi_split_path_info定义:

location ~ /test/.+[^/]\.php(/|$) {

    alias /var/www/html;

    fastcgi_split_path_info ^/test(.+?\.php)(.*)$;
    set $orig_path $fastcgi_path_info;

    try_files $fastcgi_script_name =404;

    fastcgi_pass unix:/var/run/php5-fpm.sock;
    fastcgi_index index.php;
    include fastcgi_params;

    fastcgi_param SCRIPT_FILENAME $request_filename;
    fastcgi_param PATH_INFO $orig_path;
    fastcgi_param PATH_TRANSLATED $document_root$orig_path;
}

这将允许您运行利用您的应用程序PATH_INFO安全参数。 请记住,你必须改变cgi.fix_pathinfo在你选择php.ini文件中的“1”才能正确地完成这项工作。 您可能还关闭security.limit_extensions在你php-fpm.conf文件。

结论

希望现在你可以更好地理解Nginx的FastCGI代理功能。 这种能力使Nginx能够在快速连接处理和提供静态内容方面发挥其优势,同时将动态内容的职责卸载到更适合的软件。 FastCGI允许Nginx使用大量的应用程序,在性能和安全的配置。