强制 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-Proto
和 X-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);
...
在我的 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-Proto
和 X-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);
...