如何使用Django/nginx部署仅HTTPS的站点?
我最初的问题是如何,也是唯一的回答,建议我将整个站点设置为HTTPS 考虑到我使用的是Django 1.3和nginx,那么让站点只使用HTTPS的正确方法是什么 有一个回答提到了,但有一个警告: Django在维护POST数据时无法执行SSL重定向。 请构造视图,以便重定向只在GET期间发生 关于服务器故障的一个问题,也提到了帖子丢失数据的问题,我对nginx不够熟悉,无法确定解决方案的工作情况 并注意到: 应用程序必须在以下情况下在cookie上设置安全属性: 设置它。此属性指示浏览器发送cookie 仅通过安全(HTTPS)传输,从不使用不安全(HTTP) 像Django auth这样的应用程序是否能够将cookie设置为安全的?还是我必须写更多的中间件 那么,配置Django/nginx组合以仅实现HTTPS的最佳方式是什么呢如何使用Django/nginx部署仅HTTPS的站点?,django,https,nginx,django-authentication,Django,Https,Nginx,Django Authentication,我最初的问题是如何,也是唯一的回答,建议我将整个站点设置为HTTPS 考虑到我使用的是Django 1.3和nginx,那么让站点只使用HTTPS的正确方法是什么 有一个回答提到了,但有一个警告: Django在维护POST数据时无法执行SSL重定向。 请构造视图,以便重定向只在GET期间发生 关于服务器故障的一个问题,也提到了帖子丢失数据的问题,我对nginx不够熟悉,无法确定解决方案的工作情况 并注意到: 应用程序必须在以下情况下在cookie上设置安全属性: 设置它。此属性指示浏览器发送c
- 保安
- 保存邮政数据
- 妥善处理饼干
- 与其他Django应用程序(如Django auth)的交互工作正常
- 我不知道的任何其他问题:)
https://mysite.com/search/
,它有一个搜索表单/按钮。我单击按钮,像往常一样在Django中处理表单,然后执行Django tohttp://mysite.com/search?results=“foo”
。Nginx将其重定向到https://mysite.com/search?results=“foo”
,根据需要
然而,当重定向发生时,Opera有一个可见的闪光。每次搜索都会发生这种情况,即使是对于同一个搜索词(我想https真的不会缓存:),更糟糕的是,当我在IE中测试它时,我首先得到的消息是:
您将被重定向到不安全的连接-是否继续
单击“是”后,紧接着是:
您将要通过安全连接查看页面-是否继续
尽管第二个IE警告有关闭的选项,但第一个警告没有,因此每次有人进行搜索并被重定向到结果页面时,他们至少会收到一条警告消息。如果你将整个网站都放在https后面,你不必担心django端的问题。(假设您不需要在nginx和django之间保护数据,只需要在用户和服务器之间保护数据)这是我到目前为止制定的解决方案。有两部分,配置nginx和为Django编写代码。nginx部分处理外部请求,将
http
页面重定向到https
,而Django代码处理具有http
前缀的内部URL生成。(至少是由HttpResponseRedirect()
产生的)。综合起来,它似乎工作得很好——据我所知,客户端浏览器从未看到用户自己没有键入的http
页面
第一部分,nginx配置
第二部分A,各种安全cookie设置,来自settings.py
服务器\u TYPE=“DEV”=真
=真
=True#目前仅在Django的开发分支中。
=正确 第二部分B,Django代码
请注意,可以将
HTTPS\u Response()
作为装饰程序重新写入。这样做的好处是不必检查所有代码并替换HttpResponseRedirect()
。缺点-您必须将decorator放在HttpResponseRedirect()
前面,它位于Django中的Django.http.\uuu init\uuuu.py
。我不想修改Django的代码,但这取决于您-这当然是一种选择。对于John C答案的第二部分,以及Django 1.4+
您可以将request.scheme
更改为https
,而不是扩展HttpResponseRedirect。
因为Django在Nginx的反向代理后面,所以它不知道原始请求是安全的
在Django设置中,设置以下设置:
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
然后,需要Nginx在反向代理中设置自定义头。在Nginx站点设置中:
location / {
# ...
proxy_set_header X-Forwarded-Proto $scheme;
}
这样request.scheme==“https”
和request.is\u secure()
返回True。
request.build\u absolute\u uri()
返回https://...
等等…您是说使用nginx来完成所有配置吗?您只需要将nginx设置为只响应https请求(可能会将任何非https重定向到https)。django只能在http上运行,因为它只在localhostI上与nginx对话。我将nginx配置为将所有内容重定向到https,但它没有完全起作用-使用变量重定向到另一个URL,如https://mysite.com/search?results=“abc”
,删除变量。django的文档似乎建议使用HTTP\u X\u FORWARDED\u PROTO
而不是HTTP\u X\u FORWARDED\u PROTOCOL
,这有关系吗?只要您在nginx和django设置中设置相同的头(nginx中的X-FORWARDED-PROTO),这两者都可以工作(以及任何其他名称)。我在写这篇文章时没有意识到“proto”是惯例……我更新了答案,使之与文档一致,感谢您指出。对于使用nginx和uwsgi为django服务的任何人。注意,您不需要指定“SECURE\u PROXY\u SSL\u HEADER”,因为在本例中,django已经知道请求是否安全is\u secure()
正在检查scheme
属性,该属性调用\u get\u scheme(self)
,该属性反过来应该由WSGIRequest
实现,它返回self.environ.get('wsgi.url\u scheme')。而且--您猜到了--这个环境变量由uwsgi相应地填充。如果您使用AWS ALB/ELB来处理http/https重定向,并且正在向nginx容器发送http请求,那么将头设置为
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
location / {
# ...
proxy_set_header X-Forwarded-Proto $scheme;
}