apache 2.4,mod_proxy_fcgi 不支持 .htaccess,需要另辟蹊径

apache 2.4,mod_proxy_fcgi 不支持 .htaccess,需要另辟蹊径

我使用带有 mod_proxy_fcgi 的 apache 2.4.7 来将 php 传递到 php-fpm(这将用于共享托管环境)。htaccess 对于非 php 文件工作正常,但一旦它命中通过 php 请求进行代理的重写规则,htaccess 就会被忽略。

我知道为什么会发生这种情况。问题是:我该如何解决这个问题?

问题是如何强制 apache 将对 php 文件的请求视为对本地文件的请求,然后通过代理进行处理?

我花了大量时间研究这个问题,并给出了以下“答案”作为解决方案:

1)“使用 apache 配置而不是 .htaccess”它是有效的解决方案,但不适用于共享托管环境(我不会向共享托管客户提供 apache 配置访问权限;))。

2) “不要使用 .htaccess,因为它存在性能/安全/其他问题”,那么共享主机客户还能如何控制其网站上的访问/URL 重写?此外,如果 .htaccess 不是必需的,我只会使用 nginx。

3)“将代理重写规则放入其中” - 这是不正确的,并且不起作用。

这种行为似乎不是一个错误,而是一个“功能”, https://issues.apache.org/bugzilla/show_bug.cgi?id=54887

答案1

同时,自 Apache 2.4.10 起,还有另一种选择:通过 Handler 进行代理。请参阅 Apache 文档中的示例:mod_proxy_fcgi 示例

您还可以通过创建合适的 Handler 传递,强制将请求作为反向代理请求处理。下面的示例配置将使用反向代理将所有 PHP 脚本请求传递到指定的 FastCGI 服务器。此功能在 Apache HTTP Server 2.4.10 及更高版本中可用。出于性能原因,您需要定义一个代表相同 fcgi:// 后端的工作程序。此形式的好处是它允许在服务器中正常进行 URI 到文件名的映射,并将本地文件系统结果传递到后端。当以这种方式配置 FastCGI 时,服务器可以计算最准确的 PATH_INFO。

<Proxy "fcgi://localhost/">
    ProxySet enablereuse=On
</Proxy>
<FilesMatch "\.php$">
    SetHandler "proxy:fcgi://localhost:9000"
</FilesMatch>

这允许在 .htaccess 文件中使用 RewriteRules 和身份验证。完成所有重写后,请求将传递给 php-fpm。

答案2

请注意,RewriteCond -U 将在执行实际重定向之前检查 URI 是否正确,因此会使每个请求加倍!这可能会对性能产生严重影响,尤其是在负载繁重的网站上。

我建议检查“RewriteOptions InheritBefore”,它似乎可以解决与 htaccess 继承相关的任何问题,如下所述:

了解 apache 2.4 mod_proxy_fcgi 和 htaccess 中的 RewriteRules

干杯,乔治奥

答案3

出现您将所有 php 执行都传递给快速 cgi 服务器,该服务器不知道如何使用 htaccess,因此它会忽略这些文件。如果您需要通过 Apache 使用 htaccess 文件,则需要通过 Apache 执行 php 脚本(即使用 mod_php),而不是将执行传递给另一个不知道 htaccess 的服务。

您可以重新制定重写规则,但由于这些规则是由用户控制的,因此您对此无能为力。

答案4

编辑:

解决这个问题的真正方法不是将代理的重写规则放入 php-fpm 中,而是执行以下操作:

RewriteCond %{REQUEST_URI} -U
RewriteRule (.*\.php)$ fcgi://IP:PORT/$1 [P,L]

标签外部和标签内部。

因为原始解决方案存在一个问题:如果存在“RewriteEngine On”或任何“RewriteRule”相关的规则/条件,它将导致 Apache 完全忽略主配置文件中标签内的重写规则。

以下并不完全正确

我发现我关于不在标签内部工作的想法是错误的。

RewriteMap and standard rewrite lookup of the user dirs goes here

<Directory /PATH_TO_WWW/*>
      Standard directory conf goes here

      RewriteRule ^(.*\.php)$ fcgi://IP_OF_THE_FPM:FPM_PORT/$1 [P,L]

</Directory>

基本上这个秘密(至少对我来说)我需要放置重写规则,该规则通过目录标签内部的代理来执行,这些标签是针对具有 * 的用户的公共目录的。

因此如果我在 /var/www/$username 中有用户,则目录标签应如下所示:

TL;DR:在目录标签内对普通用户目录使用代理重写规则。

相关内容