9

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,而实际上他们不是。我不确定这是否存在安全风险,但这似乎不是一个好主意。

是否存在安全风险?更好的解决方案是什么?

由于 usingX-Forwarded-Proto似乎是一种标准,因此该解决方案可能是提交给 CakePHP 核心的一个很好的补丁,所以我认为任何答案都可以合法地涉及编辑核心文件。

4

3 回答 3

3

添加请求检测器

不要编辑核心。如果您打算提交补丁,请在补丁被接受之前不要依赖您的补丁- 否则您将走上分歧之路并维护自己的 CakePHP 分支。

一旦确定了确切的实现逻辑,就可以使用请求检测器来实现它。

例如:

//AppController::beforeFilter
public function beforeFilter() {
    $this->request->addDetector('ssl', array(
        'env' => 'HTTP_X_FORWARDED_PROTO',
        'value' => 'https'
    ));
}

在此之后,您的自定义标头将被 cake 正确识别为 ssl 请求。

请注意,$_SERVER全局键被标准化为全部大写和下划线分隔,即:

$ curl --header "X-Forwarded-Proto:https" http:://yoursite.com

将填充$_SERVER['HTTP_X_FORWARDED_PROTO']- 因此这是检查的关键。

考虑(内)安全

是的,这是您应该注意的事情 - 要么禁用对您的网络服务器的直接访问,以便只有通过负载均衡器的 ip 它才会响应;或修改您的检测器,以便无论标头的值如何,它都不会为直接访问请求返回 true X-Forwarded-Proto- 如文档中所示,您可以使用回调来执行所需的任何逻辑,而不是简单地测试某些环境变量的值。

于 2013-01-13T16:00:56.647 回答
2

mod_rpaf会让你这样做。

这会根据 nginx 发送的标头将 Apache 中的 HTTPS 值设置为“on”,因此 Cake 可以开箱即用(以及在 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>
于 2013-11-14T08:59:59.367 回答
1

我发现 AD7six 的评论 - 覆盖 redirect() 函数 - 在我的仅 SSL 设置中非常有用,因为我的应用程序有一些重定向到 http。

我刚刚添加了以下内容,AppController.php因此重定向功能始终使用 https:

function redirect($url, $status = NULL, $exit = true) {
    return parent::redirect(str_replace('http://', 'https://', Router::url($url, true)));
}
于 2014-06-27T13:29:58.930 回答