如何让Symfony 2采用协议方案(http vs https)
How to let Symfony 2 adopt the protocol scheme (http vs https)
我有一个 Symfony 2 网站,它要么在开发中运行在 HTTP 上,要么在生产中运行在 HTTPS 上。
我注意到在生产中,Symfony 生成的 URL 仍然全部呈现为 HTTP。
我怎么办;
- 让框架采用当前提供网站的协议(可能是首选)?
- 或者,仅在生产环境中强制整个网站采用 HTTPS 模式?
要在您的生产环境中强制HTTPS
,您可以使用以下配置:
在你的 app/config/routing.yml
:
acme_hello:
resource: "@AcmeHelloBundle/Resources/config/routing.yml"
schemes: [https]
在你的添加app/config/routing_dev.yml
:
_main:
resource: routing.yml
schemes: [http]
如果你想在开发环境中为你的所有路由强制HTTP
。
并且在您的 @AcmeHelloBundle/Resources/config/routing.yml
中您可以放置所有路线。
有关 schemes: [https]
的更多信息以及其他使其工作的方法,您可以查看 Symfony documentation。
我使用此解决方案来强制使用 HTTP 或 HTTPS:
我在不同的环境配置文件中定义了一个 %auth_required_channel%
值:
app/config/config_dev.yml 和 app/config/config_test.yml
parameters:
auth_required_channel: 'http'
app/config/config_prod.yml
parameters:
auth_required_channel: 'https'
app/config/security.yml
此参数随后用于请求 HTTP 或 HTTPS 通道 (Symfony2 documentation):
security:
[...]
access_control:
[...]
- { path: ^/admin, roles: ROLE_ADMIN, requires_channel: %auth_required_channel% }
(改编自 old answer)
@A.L 和@AndreySobkanyuk 给出的两种解决方案均有效,但不适用于我遇到的问题。
@A.L 和@AndreySobkanyuk 给出的两种解决方案的问题在于 Symfony 2 正在尝试进行重定向。 IE。如果 URL 通过在路由配置中指定不同的协议(例如 HTTP)访问(例如 HTTPS),Symfony 2 将进行重定向(在 PHP 级别)。
在我的情况下,URL 重写发生在 Web 服务器级别 (Apache),因为我的网站将所有 URL 作为 HTTPS 提供。
我遇到的问题是,在我的模板中生成的 URL 都是使用 HTTP 协议呈现的,它们应该是 HTTPS。我假设有一种方法可以告诉 Symfony 每当它呈现 URL 时就用 HTTPS 而不是 HTTP 作为前缀。不幸的是,没有(或者至少我不知道)。
由于我的网站 运行 在负载平衡器后面,我的网络服务器不知道它应该将 URL 呈现为 HTTPS,因为负载平衡器和网络之间的内部连接服务器是 HTTP。这意味着从 Symfony 的角度来看,所有请求都是使用 HTTP 发出的,并且通过在 Symfony 路由级别上强制协议,它会导致无限重定向循环,即;
- 您通过 HTTPS 命中 URL。
- 负载平衡器将请求作为 HTTP 传递给 Web 服务器。
- 在 Symfony 中,路由被配置为使用 HTTPS,这会导致 PHP 级别的重定向。
- 回到1(无限循环)。
为了解决我的问题,我必须让我的网络服务器知道我的网站在 HTTPS 中运行。按照 How to Configure Symfony to Work behind a Load Balancer or a Reverse Proxy 页面上给出的说明,我能够解决问题,即我的网络服务器现在提供了正确的 header 信息,并且正在生成正确的 URL' s.
将所需的 header 从负载平衡器传递到 Web 服务器的最简单方法是将以下行添加到您的 web/app.php
:
Request::setTrustedProxies(array($request->server->get('REMOTE_ADDR')));
请注意,以上可能不是您特定配置的最佳解决方案。请参阅文档了解可能更适合您的设置的其他方法。
我发现这对我的情况很有用(使用 nginx)
向 nginx fcgi params 添加以下行,这是必需的,因为 Symfony2 依赖此变量,由 Web 服务器传递给 PHP,以生成正确的 URL。 Apache 默认这样做,但 nginx 需要这个特殊配置。
fastcgi_param HTTPS on;
http://blog.servergrove.com/2011/04/04/symfony2-quick-tip-generateurl-with-https-on-nginx/
假设这种情况:
- 您的 Symfony 应用程序在 Varnish 或 BigIP 等反向代理之后
- 您想使用原始客户端 IP 作为
REMOTE_ADDR
(即使用 mod_rpaf
apache 扩展)(当然在这种情况下您不能使用 trusted_proxies
值)
您可以在您的网络服务器中设置 HTTPS 环境变量,索引为 X-FORWARDED-PROTO header 值,以强制 Symfony 使用 https 协议。
在 Apache 中:
SetEnvIf x-forwarded-proto https HTTPS=on
Ho 如果你想在反向代理/负载均衡器和 twig 渲染后面使用 https,在 https 方案中你必须转发两个 scheme和 端口
示例反向代理 app.php
Request::setTrustedProxies(array('127.0.0.1), Request::HEADER_X_FORWARDED_ALL);
proxy_pass http://localhost:6081;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Port 443;
树枝
<script src="{{ asset('build/common.js') }}"></script>
将是<script src="https://www.example.com/build/common.js"></script>
我有一个 Symfony 2 网站,它要么在开发中运行在 HTTP 上,要么在生产中运行在 HTTPS 上。
我注意到在生产中,Symfony 生成的 URL 仍然全部呈现为 HTTP。
我怎么办;
- 让框架采用当前提供网站的协议(可能是首选)?
- 或者,仅在生产环境中强制整个网站采用 HTTPS 模式?
要在您的生产环境中强制HTTPS
,您可以使用以下配置:
在你的
app/config/routing.yml
:acme_hello: resource: "@AcmeHelloBundle/Resources/config/routing.yml" schemes: [https]
在你的添加
app/config/routing_dev.yml
:_main: resource: routing.yml schemes: [http]
如果你想在开发环境中为你的所有路由强制
HTTP
。并且在您的
@AcmeHelloBundle/Resources/config/routing.yml
中您可以放置所有路线。
有关 schemes: [https]
的更多信息以及其他使其工作的方法,您可以查看 Symfony documentation。
我使用此解决方案来强制使用 HTTP 或 HTTPS:
我在不同的环境配置文件中定义了一个 %auth_required_channel%
值:
app/config/config_dev.yml 和 app/config/config_test.yml
parameters:
auth_required_channel: 'http'
app/config/config_prod.yml
parameters:
auth_required_channel: 'https'
app/config/security.yml
此参数随后用于请求 HTTP 或 HTTPS 通道 (Symfony2 documentation):
security:
[...]
access_control:
[...]
- { path: ^/admin, roles: ROLE_ADMIN, requires_channel: %auth_required_channel% }
(改编自 old answer)
@A.L 和@AndreySobkanyuk 给出的两种解决方案均有效,但不适用于我遇到的问题。
@A.L 和@AndreySobkanyuk 给出的两种解决方案的问题在于 Symfony 2 正在尝试进行重定向。 IE。如果 URL 通过在路由配置中指定不同的协议(例如 HTTP)访问(例如 HTTPS),Symfony 2 将进行重定向(在 PHP 级别)。
在我的情况下,URL 重写发生在 Web 服务器级别 (Apache),因为我的网站将所有 URL 作为 HTTPS 提供。
我遇到的问题是,在我的模板中生成的 URL 都是使用 HTTP 协议呈现的,它们应该是 HTTPS。我假设有一种方法可以告诉 Symfony 每当它呈现 URL 时就用 HTTPS 而不是 HTTP 作为前缀。不幸的是,没有(或者至少我不知道)。
由于我的网站 运行 在负载平衡器后面,我的网络服务器不知道它应该将 URL 呈现为 HTTPS,因为负载平衡器和网络之间的内部连接服务器是 HTTP。这意味着从 Symfony 的角度来看,所有请求都是使用 HTTP 发出的,并且通过在 Symfony 路由级别上强制协议,它会导致无限重定向循环,即;
- 您通过 HTTPS 命中 URL。
- 负载平衡器将请求作为 HTTP 传递给 Web 服务器。
- 在 Symfony 中,路由被配置为使用 HTTPS,这会导致 PHP 级别的重定向。
- 回到1(无限循环)。
为了解决我的问题,我必须让我的网络服务器知道我的网站在 HTTPS 中运行。按照 How to Configure Symfony to Work behind a Load Balancer or a Reverse Proxy 页面上给出的说明,我能够解决问题,即我的网络服务器现在提供了正确的 header 信息,并且正在生成正确的 URL' s.
将所需的 header 从负载平衡器传递到 Web 服务器的最简单方法是将以下行添加到您的 web/app.php
:
Request::setTrustedProxies(array($request->server->get('REMOTE_ADDR')));
请注意,以上可能不是您特定配置的最佳解决方案。请参阅文档了解可能更适合您的设置的其他方法。
我发现这对我的情况很有用(使用 nginx)
向 nginx fcgi params 添加以下行,这是必需的,因为 Symfony2 依赖此变量,由 Web 服务器传递给 PHP,以生成正确的 URL。 Apache 默认这样做,但 nginx 需要这个特殊配置。
fastcgi_param HTTPS on;
http://blog.servergrove.com/2011/04/04/symfony2-quick-tip-generateurl-with-https-on-nginx/
假设这种情况:
- 您的 Symfony 应用程序在 Varnish 或 BigIP 等反向代理之后
- 您想使用原始客户端 IP 作为
REMOTE_ADDR
(即使用mod_rpaf
apache 扩展)(当然在这种情况下您不能使用trusted_proxies
值)
您可以在您的网络服务器中设置 HTTPS 环境变量,索引为 X-FORWARDED-PROTO header 值,以强制 Symfony 使用 https 协议。
在 Apache 中:
SetEnvIf x-forwarded-proto https HTTPS=on
Ho 如果你想在反向代理/负载均衡器和 twig 渲染后面使用 https,在 https 方案中你必须转发两个 scheme和 端口
示例反向代理 app.php
Request::setTrustedProxies(array('127.0.0.1), Request::HEADER_X_FORWARDED_ALL);
proxy_pass http://localhost:6081;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Port 443;
树枝
<script src="{{ asset('build/common.js') }}"></script>
将是<script src="https://www.example.com/build/common.js"></script>