CakePHP的(我见过的所有版本)核对$_SERVER['HTTPS']
看到一个请求是否已经取得了HTTPS,而不是简单的HTTP的。
我使用nginx的作为负载平衡器,它的后面是Apache的应用服务器。 由于SSL连接的终点为负载平衡器, $_SERVER['HTTPS']
没有设置尽可能CakePHP的关注。
我想找到检测到应用服务器上的HTTPS的安全方式。
到目前为止,我已经把这个变成我的CakePHP的配置:
$request_headers = getallheaders();
if ( (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS']) || ( isset($request_headers['X-Forwarded-Proto']) && $request_headers['X-Forwarded-Proto'] == 'https' ) ) {
$ssl = true;
// overwrite environment vars (ugly) since CakePHP won't honour X-Forwarded-Proto
$_SERVER['HTTPS'] = 'on';
$_ENV['HTTPS'] = 'on';
} else {
$ssl = false;
}
然后在nginx的配置,我用proxy_set_header X-Forwarded-Proto https;
该标志添加到负载平衡器和后端应用服务器之间的任何请求。
这工作完全正常,但任何人进行直接请求到应用服务器可以将它们误以为他们正在浏览的通过SSL时,他们没有。 我不知道这是否是一个安全隐患,但它似乎并不像一个好主意。
它是一个安全隐患? 有什么更好的解决办法?
由于使用X-Forwarded-Proto
似乎是一个标准的东西 ,解决方案可能会被提交给CakePHP的核心好的面片,所以我觉得任何的回答可以合法地参与编辑的核心文件太大。
mod_rpaf会让你做到这一点。
这在Apache中设置HTTPS值设置为“上”的基础上nginx的发送,从而将滤饼开箱的报头(以及在运行Apache任何其他应用程序)。
它还纠正REMOTE_ADDR,SERVER_PORT和HTTP_HOST的值。
下面是我的示例配置:
<IfModule mod_rpaf.c>
RPAF_Enable On
RPAF_ProxyIPs 127.0.0.1 10.0.0.0/24
RPAF_SetHostName On
RPAF_SetHTTPS On
RPAF_SetPort On
</IfModule>
# If mod_rewrite redirects then we lose the HTTPS status to REDIRECT_HTTPS.
# This resets it back. This happens with Cake's front controller
<IfModule setenvif_module>
SetEnvIf REDIRECT_HTTPS on HTTPS=on
</IfModule>
添加请求检测
请勿编辑核心。 如果你的目的是要提交一个补丁,不依赖于你的补丁,直到它的接纳, -否则你是在道路上发散,和维护自己的CakePHP的叉。
一旦你确定你确切的实现逻辑,你可以使用一个请求检测兑现它。
例如:
//AppController::beforeFilter
public function beforeFilter() {
$this->request->addDetector('ssl', array(
'env' => 'HTTP_X_FORWARDED_PROTO',
'value' => 'https'
));
}
在此之后,您的自定义标题会正确地被蛋糕作为SSL请求标识。
注意的键$_SERVER
全球被归为全部大写和下划线分隔,即:
$ curl --header "X-Forwarded-Proto:https" http:://yoursite.com
将填充$_SERVER['HTTP_X_FORWARDED_PROTO']
-因为这是这种检查的关键。
帐户(在)安全
是的,这是你应该照顾的 - 这样只能通过负载均衡器的IP将它在所有响应或者禁用直接访问您的网络服务器; 或修改您的探测器,使其不会在价值的直接访问请求返回true,不论X-Forwarded-Proto
头-如在文档中,你可以使用一个回调来执行任何逻辑要求,而不是简单地测试值一些环境变量。
我发现AD7six的注释 - 覆盖重定向()函数 - 在我的SSL-只设置非常有帮助的,因为我的应用程序有一些重定向将HTTP。
我只是添加了以下到AppController.php
所以重定向功能始终使用https:
function redirect($url, $status = NULL, $exit = true) {
return parent::redirect(str_replace('http://', 'https://', Router::url($url, true)));
}