将Heroku应用程序的HTTP重定向安全地转换为HTTPS

4
我正在尝试将我的Django + Heroku应用程序从http重定向到https,但我惊讶地发现没有任何安全和直接的方法。 根据Heroku的说法
问题: 您已经配置了SSL端点,现在希望您的应用程序对所有请求使用https。
解决方案: 由于Heroku路由器不提供此功能,因此必须在应用程序级别执行重定向。您应该将重定向逻辑编码到您的应用程序中。
在幕后,Heroku路由器(超过)写入X-Forwarded-Proto和X-Forwarded-Port请求头。当X-Forwarded-Proto不是https而是http时,应用程序检查X-Forwarded-Proto并响应重定向响应。 DjangoSECURE_SSL_REDIRECT设置为True
所以必须在Django中完成。我找到了这个最完整的答案,这个也相似。

Django 1.8 will have core support for non-HTTPS redirect (integrated from django-secure):

SECURE_SSL_REDIRECT = True
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')

In order for SECURE_SSL_REDIRECT to be handled you have to use the SecurityMiddleware:

MIDDLEWARE = [
    ...
    'django.middleware.security.SecurityMiddleware',
]
注意两者都使用
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')

似乎没有这个设置,Heroku 上无法正常工作。现在来到有趣/可怕的部分。如 文档 中所解释的:
SECURE_SSL_REDIRECT

如果将其设为 True 导致无限重定向,则可能意味着您的站点运行在代理之后,无法确定哪些请求是安全的,哪些不是安全的。您的代理可能会设置一个标头来指示安全请求;您可以通过找出该标头并相应地配置 SECURE_PROXY_SSL_HEADER 设置来纠正问题。
然后,检查关于 SECURE_PROXY_SSL_HEADER 的情况:
警告
如果在不知情的情况下设置此项,您可能会在站点上开放安全漏洞。而且如果您未能在应该设置时设置它。认真点。

这让我想要找到一个更安全的解决方案... 在另一个问题中,它说应该没问题,但我不认为这足以忽略这样一个警告。

Django真的没有其他实现方式是安全的吗?

我正在使用1.11版本。


更新:
我找到了django-sslify package,但它还需要设置SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https'),所以我猜在潜在的安全漏洞方面没有什么区别。如果这个假设不正确,请纠正我。

上周实际上有一个类似的问题被发布在Stack Overflow上,但是没有得到答案... - J0ANMM
只是想说,我在Python 3.6.6 / Django 2.1 / Heroku / Gunicorn混合环境下成功使用了这个包。 - Marc
你能否写一个扩展回答,解释一下你是如何做到的?这可能会对很多人有所帮助 :) - J0ANMM
1
感谢@J0ANMM提醒我。事实证明,仍然存在可能的问题。我使用pip安装了Randall的工作,并按照文档进行了配置(包括Heroku的SECURE_PROXY_SSL_HEADER),但是唯一解决的问题是重定向问题和www和非www的https错误。http到https的重定向没有起作用。由于我无法确认我的应用程序是否是阻止器还是代码需要更新,因此我进入我的DNS(CloudFlare)并使用规则转发到https。在停机时间内,我计划在Heroku上启动一个测试项目以确认软件包操作,直到那时我将继续运行。 - Marc
我在这里找到了答案,对我有用!https://dev59.com/4VUM5IYBdhLWcg3wQOXw#49112662 - Karam Qusai
1个回答

0

我认为如果你盲目使用它,HTTP_X_FORWARDED_PROTO是危险的,因为它会让Django认为你正在接收HTTPS请求(即使HTTP_X_FORWARDED_PROTO实际上是伪造的)。

但是,如果你在一个正常运行的负载均衡/代理后面(比如AWS),那么你可以确信HTTP_X_FORWARDED_PROTO被正确设置了。在这种情况下,HTTP_X_FORWARDED_PROTO用于告诉Django没问题,不用担心(因为你信任代理不会允许通过伪造的头部),并停止尝试不断重定向到SSL。

最后,即使你没有使用SECURE_SSL_REDIRECT = True(例如,如果重定向是在正确配置的Web服务器中发生的),在代理/负载均衡器后面,HTTP_X_FORWARDED_PROTO也是必需的,因为它还会影响请求上的is_secure()函数,如果你的代理程序吞噬了原始请求(例如,在客户端和代理/负载均衡器之间使用HTTPS,而在代理/负载均衡器和Web服务器之间使用HTTP),则该函数将始终为false。

来源:Django文档:SECURE_PROXY_SSL_HEADER


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