问题
In my Symfony2 app I have a firewall set up so that everything under the /admin
route needs to be run through https, however when deployed I get a redirect loop. I've read the documentation on the Symfony2 site on firewalls, and setting up a login form. I've also read a few Stack Overflow articles and attempted their solutions, but nothing so far.
Below is my configuration, is there something I'm missing?
(As far as I know the server is running Apache, I've no direct access to server configuration from my hosting provider)
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}
回答1:
Based on your own answer, it seems your website is behind a Load Balancer or a Reverse Proxy (since you need to check on the HTTP_X_FORWARDED_PROTO
server variable, which is normally empty).
Your hosting provider may have put such a setup in place without your explicit knowledge. By default, Symfony ignores the X-Forwarded-Proto
and X-Forwarded-For
headers, unless you add the proxy to a whitelist in your app/config/config.yml
file:
framework:
trusted_proxies: [127.0.0.1, ::1]
Where 127.0.0.1
and ::1
should be replaced by the actual proxy/proxies that your hosting provider uses (they should be able to tell you that).
Doing that should make it work without hacking the app.php file.
回答2:
Update: Fixed the issue. It turns out some server variables were not set on the hosting provider.
For future reference, add the following under app.php
in the web or public_html directory. Might be a dirty hack, but it fixed the issue for me.
if($_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https')
{
$_SERVER['HTTPS'] = 'on';
$_SERVER['SERVER_PORT'] = 443;
}
回答3:
Based on the correct answer by @Oldskool , on SF > 3.3 you can use env
variables to set trusted_proxies
in SF4, as the node were removed since that version.
In Symfony >3.2 <4, the code is this:
# 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();
// ...
If you are on SF4, instead, you can use the env
variables as the front controller (in public/index.php
) reads them.
So, simply add the env
variable TRUSTED_PROXIES
putting in all your trusted proxies, separated by a comma ",":
TRUSTED_PROXIES = xxx.xxx.xxx.xxx/x,xxx.xxx.xxx.xxx/x,xxx.xxx.xxx.xxx/x
As a final reference, you can check the issue on GitHub about the infinite loop caused by forcing the https.
ON HEROKU
As a simple reference as I had this problem with Heroku
If you have troubles forcing to https and your app is on Heroku:
You have to follow the instructions provided by Heroku (only for 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);
For 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);
...
来源:https://stackoverflow.com/questions/34118854/redirect-loop-in-symfony2-when-forcing-https