如何让Symfony 2采用协议方案(http vs https)

12

我有一个Symfony 2网站,在开发中运行HTTP或在生产中运行HTTPS。

我注意到在生产环境中,Symfony生成的URL仍然都是以HTTP渲染的。

我应该如何做:

  1. 让框架采用当前网站所使用的协议(可能更好)?
  2. 或者,在生产中强制将整个网站设置为仅使用HTTPS模式?

你是如何生成URL的?使用 {{ path() }} 吗? - A.L
我在我的Twig模板中使用{{ url(' ... ') }} - Luke
6个回答

11

@A.L和@AndreySobkanyuk提供的两种解决方案都是有效的,但不适用于我遇到的问题。

问题在于@A.L和@AndreySobkanyuk提供的两种解决方案中,Symfony 2试图进行重定向。也就是说,如果通过某个协议(例如HTTP)访问URL,而路由配置中指定了不同的协议(例如HTTPS),则Symfony 2将在PHP层面上执行重定向。

在我的情况下,URL重写发生在Web服务器级别(Apache),因为我的网站将所有URL视为HTTPS。

我遇到的问题是,在我的模板中生成的所有URL都使用HTTP协议呈现,而它们应该是HTTPS。我认为应该有一种方法告诉Symfony每当它呈现URL时,要使用HTTPS前缀而不是HTTP。不幸的是,没有这样的方法(或者至少我不知道有)。

由于我的网站位于负载均衡器后面,我的Web服务器不知道它应该将URL呈现为HTTPS,因为负载均衡器和Web服务器之间的内部连接是HTTP。这意味着从Symfony的角度来看,所有请求都是使用HTTP发出的,并且在Symfony路由级别上强制协议会导致无限重定向循环,即:

  1. 您通过HTTPS访问URL。
  2. 负载均衡器将请求作为HTTP传递给Web服务器。
  3. 在Symfony中,路由被配置为使用HTTPS,这会导致在PHP层面上重定向。
  4. 回到1(无限循环)。

要解决我的问题,我必须让我的Web服务器意识到我的网站以HTTPS运行。按照如何配置Symfony在负载均衡器或反向代理后工作页面上的说明,我能够解决问题,即现在我的Web服务器正在接收正确的头信息并生成正确的URL。

将所需的标头从负载均衡器传递到Web服务器的最简单方法是将以下行添加到web/app.php文件中:

Request::setTrustedProxies(array($request->server->get('REMOTE_ADDR')));

请注意,以上可能不是您特定配置的最佳解决方案。请参阅文档以了解其他更适合您设置的方法。


1
我总是在发布答案之前测试代码,所以我使用 resource 检查了schemes:[https],对我来说效果很好。 - chapay
1
我所有使用 {{ url() }} 生成的 URL 都是基于 https 的。 - chapay
1
@AndreySobkanyuk; 你是在负载均衡器后面吗?这可能是因为你没有在负载均衡器后面,所以它对你起作用。在我理解问题之前,我假设你的解决方案强制渲染HTTPS URL,但实际上并不是这样。当使用HTTP访问URL时,它会在PHP级别强制重定向到HTTPS URL,这导致我陷入了无限重定向循环。 - Luke
很遗憾,我无法帮助您解决负载均衡器的问题,这是另一个问题。当然,当您尝试访问基于http的URL时,Symfony会尝试重定向您。但是,正如我已经说过的,如果您使用我的解决方案,则使用url()扩展生成的URL必须基于https。如果您的URL不是基于https的,则您正在错误地操作。 - chapay
1
是的,看起来我们回答了不同的问题 :) 无论如何,很高兴你找到了解决方案。 - chapay
显示剩余4条评论

7

5

为了在您的生产环境中强制使用HTTPS,您可以使用以下配置:

  1. In your app/config/routing.yml:

    acme_hello:
        resource: "@AcmeHelloBundle/Resources/config/routing.yml"
        schemes: [https]
    
  2. In your add app/config/routing_dev.yml:

    _main:
        resource: routing.yml
        schemes: [http]
    

    if you want to force HTTP for all your routes in development environment.

  3. And in your @AcmeHelloBundle/Resources/config/routing.yml you can place all your routes.

想要了解更多关于schemes: [https]和其他使其工作的方法,您可以查看Symfony文档


好的。这可能有效。然而,当像您所示的那样将其添加到“资源”中时,对我来说似乎不起作用(已清除缓存)。这绝对是由框架配置控制的事情,而不是个别捆绑包。 - Luke
1
@Luke,Symfony2文档中写道:“Symfony会自动生成一个HTTPS方案的绝对URL”,这对你有用吗?那么关于另一条语句,“使用HTTP路径[...]将自动重定向到相同的URL[...],使用HTTPS方案”呢? - A.L
1
不幸的是,这对我似乎不起作用。我开始怀疑这可能与我在负载均衡器或其他什么东西之后有关。请理解,这并不是因为网站在HTTPS上无法正常工作,它确实可以。只是模板中生成的URL是HTTP而不是应该是HTTPS。 - Luke

3
假设情况如下:
  • 您的Symfony应用程序在反向代理(如Varnish或BigIP)后面
  • 您想要使用原始客户端IP作为REMOTE_ADDR(即使用mod_rpaf apache扩展)(当然,在这种情况下,您无法使用trusted_proxies值)

您可以在Web服务器上设置HTTPS环境变量,以X-FORWARDED-PROTO标头值为索引,强制Symfony使用https协议。

在Apache中:

SetEnvIf x-forwarded-proto https HTTPS=on

2

如果您想在反向代理/负载均衡器后面使用https,并且希望twig渲染的url/资源也使用https方案,则需要同时转发schemeport

例如反向代理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;

twig

<script src="{{ asset('build/common.js') }}"></script>

将会是<script src="https://www.example.com/build/common.js"></script>


1
我使用了这个解决方案来强制使用HTTP或HTTPS:
我在不同的环境配置文件中定义了一个“%auth_required_channel%”值: app/config/config_dev.ymlapp/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文档):

security:
    [...]
    access_control:
        [...]
        - { path: ^/admin, roles: ROLE_ADMIN, requires_channel: %auth_required_channel% }

适应自旧答案

1
这只会在受保护的端点上强制执行协议。我需要在整个网站上强制执行。问题也不是强制执行协议,而是生成了不正确的URL。即使我强制使用HTTPS,仍然生成基于HTTP的URL。 - Luke
您的回答仅适用于安全包指定的路由。防火墙应用于所有规则,它与包没有关联。我不知道路由器是否知道路由使用HTTP还是HTTPS通道。不管怎样,我刚刚用这段代码检查了一下,在生产环境中Symfony2将请求从http://... 重定向到 https://... - A.L
好的。然后,使用安全设置,我如何强制我的网站上的所有路由都是HTTPS,而不仅仅是那些在“/admin”后面的路由? - Luke
也许最后一条规则是 - { path: ^/, requires_channel: %auth_required_channel% }?很难确定,没有查看您的 security.yml 文件,请在您的问题中添加您的配置。 - A.L
尝试了这个(清除了我的缓存)。不幸的是,它似乎没有起作用。模板中的所有URL仍然生成为基于HTTP的URL。 - Luke
显示剩余6条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接