Apache 2.4 + PHP-FPM和授权头部信息

48

摘要: Apache 2.4的mod_proxy似乎没有将授权标头传递给PHP-FPM。有没有办法解决这个问题?

详细版本: 我正在运行一个带有Apache 2.4和PHP-FPM的服务器。我同时使用APC进行opcode缓存和用户缓存。如互联网所建议的那样,我使用Apache 2.4的mod_proxy_fcgi代理请求到FPM,就像这样:

ProxyPassMatch ^/(.*\.php)$ fcgi://127.0.0.1:9000/foo/bar/$1
设置工作正常,除了一个问题:APC捆绑的apc.php用于监视APC状态不允许我登录(查看用户缓存条目所需)。当我点击“用户缓存条目”以查看用户缓存时,它要求我登录。 点击登录按钮会显示通常的HTTP登录表单,但输入正确的用户名和密码并不能成功登录。 当使用mod_proxy + php-fpm时,此功能在运行mod_php时完美运行。
经过一些谷歌搜索,我发现其他人也遇到了同样的问题,并且找出了问题所在,是因为Apache没有将Authorization HTTP标头传递到外部FastCgi进程。不幸的是,我只找到了适用于mod_fastcgi的修复方法,如下所示:
FastCgiExternalServer /usr/lib/cgi-bin/php5-fcgi -host 127.0.0.1:9000 -pass-header Authorization

有没有相应的设置或解决方法也适用于mod_proxy_fcgi?


感谢提供“-pass-header Authorization”代码片段!对我在使用fastcgi时非常有帮助。 - Sergio
6个回答

108

出于"安全原因",各种Apache模块都会剥离Authorization头信息。它们都有不同的晦涩设置,您可以调整这些设置以覆盖此行为,但是您需要确定究竟是哪个模块有问题。

您可以通过env将头信息直接传递给PHP来解决此问题:

SetEnvIf Authorization "(.*)" HTTP_AUTHORIZATION=$1

另请参见 Zend Server Windows - Authorization header is not passed to PHP script

在某些情况下,即使直接使用这种方式也无法正常工作,您还必须更改您的PHP代码以访问$_SERVER['REDIRECT_HTTP_AUTHORIZATION']而不是$_SERVER['HTTP_AUTHORIZATION']。请参见当在Apache RewriteRule指令中设置环境变量时,是什么导致变量名以“REDIRECT_”为前缀?


7
这可能会帮助使用PHP 5.5+和Apache 2.4的用户。在.htaccess文件中添加SetEnvIf Authorization "(.*)" HTTP_AUTHORIZATION=$1之后,您必须使用$_SERVER['REDIRECT_HTTP_AUTHORIZATION']变量,而不是$_SERVER['HTTP_AUTHENTICATION']。 - Rahi
在哪里添加这个=¿? - Alberto Acuña
3
针对 Apache 配置,在 .htaccess 或 /etc/httpd/conf 中。 - Rich
去掉“安全原因”下的Auth头是否有些多余或者误导?你对.htaccess文件的修改对我很有用,但是我在想,从整体上通过Auth头是否会产生什么副作用。 - Bytech
@Bytech:我认为这几乎总是没有意义的。例如,mod_fcgid会保留此标头,并且其文档说:“仅在绝对必要时传递这些请求标头。”(http://httpd.apache.org/mod_fcgid/mod/mod_fcgid.html#fcgidpassheader),但他们没有给出任何理由。我在`mod_fcgid`历史记录中没有看到任何进一步解释这一点的内容。也许可以开一个新问题“为什么mod_fcgid保留授权标头”,并在此处链接?我想,如果Web服务器不信任其托管的应用程序,这可能是个好主意? - Rich

59

这个问题花费了我很长时间才解决,因为它在mod_proxy或mod_proxy_fcgi文档中并没有被记录。

请在您的apache配置或.htaccess文件中添加以下指令:

CGIPassAuth on

详情请查看此处


4
请注意,此方法仅适用于Apache 2.4.13或更高版本,即在Ubuntu 15.10及之前的任何版本上都不可使用。 - Berend de Boer
1
这个解决方案更加合理,因为它更接近于代理设置,禁用了传递身份验证标头,即: <FilesMatch .php$> SetHandler "proxy:fcgi://127.0.0.1:9000" </FilesMatch> CGIPassAuth on - Julz
1
谢谢你,这绝对是最好的答案。请注意,这仅适用于使用 SetHandler 而不是更早的 ProxyPassMatch 方法。 - Gannet

3

最近我遇到了这个arch的问题。

在我的环境中,php-fpm的代理配置如下:

<IfModule proxy_module>
    ProxyPassMatch ^/(.*\.php)$ fcgi://127.0.0.1:9000/usr/local/apache2/htdocs/$1
    ProxyTimeout 1800
</IfModule>

我已经解决了问题,设置了以下的SetEnvIf指令:
<IfModule proxy_module>
    SetEnvIf Authorization "(.*)" HTTP_AUTHORIZATION=$1
    ProxyPassMatch ^/(.*\.php)$ fcgi://127.0.0.1:9000/usr/local/apache2/htdocs/$1
    ProxyTimeout 1800
</IfModule>

1

我已经添加了

SetEnvIf Authorization "(.*)" HTTP_AUTHORIZATION=$1

在VirtualHost节点内部

<VirtualHost *:80>
    SetEnvIf Authorization "(.*)" HTTP_AUTHORIZATION=$1

0
这是我需要添加的内容,以使其适用于特定的主机。出于某种原因,关键是REDIRECT_HTTP_AUTHORIZATION而不是HTTP_AUTHORIZATION
RewriteRule . /index.php [L,E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]

$token = $_SERVER['HTTP_AUTHORIZATION'] ?? ($_SERVER['REDIRECT_HTTP_AUTHORIZATION'] ?? null);

-2

我没有找到与mod_proxy_fcgi相似的设置,但它默认情况下对我有效。它会要求用户授权(像往常一样使用.htaccess),php会接受它,并且像mod_php或fastcgi和pass-header一样工作。我不知道这是否有帮助...

编辑: 仅当使用DirectoryIndex时,它才适用于teszt.com/...如果我传递php文件名(即使是index.php!),它就无法正常工作,不会将授权传递给php。这对我来说是一个障碍,但我不想降级到apache 2.2(和mod_fastgi),所以我迁移到了nginx(在这台机器上也是如此)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接