强制 https 时在 symfony2 中重定向循环

Redirect Loop in symfony2 when forcing https

在我的 Symfony2 应用程序中,我设置了一个防火墙,因此 /admin 路由下的所有内容都需要通过 https 运行,但是在部署时我得到一个重定向循环。我已经阅读了有关防火墙的 Symfony2 站点上的文档,并设置了登录表单。我还阅读了一些 Stack Overflow 文章并尝试了他们的解决方案,但到目前为止还没有。

以下是我的配置,我是否遗漏了什么?

(据我所知服务器是 运行ning Apache,我无法从我的托管服务提供商直接访问服务器配置)

access_control:
    # require ROLE_ADMIN for /admin*
    - { path: ^/login, roles: IS_AUTHENTICATED_ANONYMOUSLY, requires_channel: https }
    - { path: ^/login_check, roles: IS_AUTHENTICATED_ANONYMOUSLY, requires_channel: https }
    - { path: ^/admin*, roles: ROLE_ADMIN, requires_channel: https}

更新:修复了问题。原来有些服务器变量没有在托管服务提供商上设置。

为了将来参考,在网络或 public_html 目录中的 app.php 下添加以下内容。可能是一个肮脏的 hack,但它为我解决了这个问题。

if($_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https')
{ 
  $_SERVER['HTTPS'] = 'on';
  $_SERVER['SERVER_PORT'] = 443;
}

根据您自己的回答,您的网站似乎位于负载均衡器或反向代理之后(因为您需要检查 HTTP_X_FORWARDED_PROTO 服务器变量,该变量通常为空)。

您的托管服务提供商可能在您明确不知情的情况下进行了此类设置。默认情况下,Symfony 会忽略 X-Forwarded-ProtoX-Forwarded-For headers,除非你 add the proxy to a whitelist 在你的 app/config/config.yml 文件中:

framework:
    trusted_proxies:  [127.0.0.1, ::1]

其中 127.0.0.1::1 应替换为您的托管服务提供商使用的实际 proxy/proxies(他们应该能够告诉您)。

这样做应该可以在不破解 app.php 文件的情况下工作。

根据@Oldskool 的正确答案,在 SF > 3.3 上,您可以使用 env 变量在 SF4 中设置 trusted_proxies,如 the node were removed since that version.

在Symfony >3.2 <4中,代码是这样的:

# web/app.php

// BEFORE
// ...
$kernel = new AppKernel('prod', false);
Request::setTrustedHeaderName(Request::HEADER_FORWARDED, null);
$request = Request::createFromGlobals();
// ...

// AFTER
// ...
$kernel = new AppKernel('prod', false);
Request::setTrustedHeaderName(Request::HEADER_FORWARDED, null);
Request::setTrustedProxies(['192.0.0.1', '10.0.0.0/8']);
$request = Request::createFromGlobals();
// ...

如果您使用的是 SF4,您可以使用 env 变量作为前端控制器(在 public/index.php 中)读取它们。

因此,只需添加 env 变量 TRUSTED_PROXIES 放入所有受信任的代理,并以逗号“,”分隔:

TRUSTED_PROXIES = xxx.xxx.xxx.xxx/x,xxx.xxx.xxx.xxx/x,xxx.xxx.xxx.xxx/x

作为最后的参考,您可以查看 issue on GitHub about the infinite loop caused by forcing the https.

在 HEROKU

作为一个简单的参考,因为我在使用 Heroku 时遇到了这个问题

如果您遇到问题 forcing to https 并且您的应用程序在 Heroku 上:

您必须遵循 instructions provided by Heroku(仅适用于 SF <= 3.2):

// web/app.php

Request::setTrustedProxies(array($request->server->get('REMOTE_ADDR')));
Request::setTrustedHeaderName(Request::HEADER_FORWARDED, null);
Request::setTrustedHeaderName(Request::HEADER_CLIENT_HOST, null);

对于 Symfony > 3.2 (instructions here for SF4):

// SF >= 4: public/index.php
...
$kernel = new Kernel($env, $debug);
$request = Request::createFromGlobals();

// Add this
Request::setTrustedProxies(array($request->server->get('REMOTE_ADDR')), Request::HEADER_X_FORWARDED_ALL ^ Request::HEADER_X_FORWARDED_HOST);

$response = $kernel->handle($request);
...