在我的Symfony2应用程序中,我设置了一个防火墙,以便/admin
路由下的所有内容都需要通过https运行,但在部署时,我会得到一个重定向循环。我已经阅读了Symfony2网站上关于防火墙的文档,并设置了登录表单。我还阅读了一些Stack Overflow文章,并尝试了他们的解决方案,但到目前为止还没有。
下面是我的配置,是不是缺少什么?
(据我所知,服务器正在运行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}
更新:修复了该问题。事实证明,一些服务器变量没有在宿主提供程序上设置。
为了将来参考,请在web或public_html目录的app.php
下添加以下内容。可能是一个肮脏的黑客,但它为我解决了问题。
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
标头,除非您将代理添加到app/config/config.yml
文件的白名单中:
framework:
trusted_proxies: [127.0.0.1, ::1]
其中127.0.0.1
和::1
应替换为托管提供商使用的实际代理(他们应该能够告诉您)。
这样做应该可以让它在不侵入app.php文件的情况下工作。
根据@Oldskool的正确答案,在SF>3.3上,您可以使用env
变量在SF4中设置trusted_proxies
,因为该节点已从该版本删除。
在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
作为最后的参考,您可以在GitHub上查看强制https
导致的无限循环的问题。
HEROKU
作为一个简单的参考,因为我在Heroku上遇到了这个问题
如果你在强制使用https
时遇到问题,并且你的应用程序在Heroku:上
您必须遵循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(此处针对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);
...