我最初的问题是如何为Django登录页面启用HTTPS,以及唯一的响应,建议我 - 将整个站点设置为仅限HTTPS.
鉴于我正在使用Django 1.3和nginx,那么使网站成为HTTPS的正确方法是什么?
一个回复提到了一个中间件解决方案,但有一点需要注意:
Django在维护POST数据时无法执行SSL重定向.请构建您的视图,以便重定向仅在GET期间发生.
有关nginx重写为https的服务器故障的问题,还提到了POST丢失数据的问题,而且我对nginx不太熟悉,无法确定解决方案的工作情况.
而且EFF建议只使用HTTPS,请注意:
应用程序必须在设置cookie时设置Secure属性.此属性指示浏览器仅通过安全(HTTPS)传输发送cookie,从不安全(HTTP).
像Django-auth这样的应用程序是否能够将cookie设置为安全?或者我是否必须编写更多中间件?
那么,在以下方面,配置Django/nginx组合以实现仅HTTPS的最佳方法是什么?
安全
保存POST数据
饼干处理得当
与其他Django应用程序(如Django-auth)的交互,正常工作
我不知道的任何其他问题:)
编辑 - 我在测试多个浏览器时发现的另一个问题.假设我有一个URL https://mysite.com/search/
,它有一个搜索表单/按钮.我按一下按钮,程序在Django像往常一样的形式,做一个Django HttpResponseRedirect来http://mysite.com/search?results="foo"
.https://mysite.com/search?results="foo"
根据需要,Nginx将其重定向到.
但是 - 重定向发生时,Opera有一个可见的闪存.它发生在每次搜索,即使是相同的搜索词(我猜https真的不缓存:)更糟糕的是,当我在IE中测试它时,我首先得到的消息:
您将被重定向到不安全的连接 - 继续?
单击"是"后,紧接着是:
您即将通过安全连接查看页面 - 继续吗?
虽然第二个IE警告可以选择关闭它 - 但第一个警告没有,所以每当有人进行搜索并被重定向到结果页面时,它们至少会收到一条警告消息.
对于John C的答案的第二部分,以及Django 1.4 + ......
不是扩展HttpResponseRedirect的,您可以更改request.scheme
到https
.因为Django支持Nginx的反向代理,所以它不知道原始请求是否安全.
在Django设置中,设置SECURE_PROXY_SSL_HEADER设置:
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
然后,您需要Nginx在反向代理中设置自定义标头.在Nginx站点设置中:
location / { # ... proxy_set_header X-Forwarded-Proto $scheme; }
这样request.scheme == 'https'
并request.is_secure()
返回True.
request.build_absolute_uri()
返回https://...
等......
这是我到目前为止已经解决的解决方案.有两个部分,配置nginx,以及为Django编写代码.nginx部分处理外部请求,重定向http
页面https
,Django代码处理具有前缀的内部 URL生成http
.(至少,由a产生的那些HttpResponseRedirect()
).结合起来,似乎运行良好 - 据我所知,客户端浏览器永远不会看到http
用户自己没有键入的页面.
# nginx.conf # Redirects any requests on port 80 (http) to https: server { listen 80; server_name www.mysite.com mysite.com; rewrite ^ https://mysite.com$request_uri? permanent; # rewrite ^ https://mysite.com$uri permanent; # also works } # django pass-thru via uWSGI, only from https requests: server { listen 443; ssl on; ssl_certificate /etc/ssl/certs/mysite.com.chain.crt; ssl_certificate_key /etc/ssl/private/mysite.com.key; server_name mysite.com; location / { uwsgi_pass 127.0.0.1:8088; include uwsgi_params; } }
SERVER_TYPE ="DEV"
SESSION_COOKIE_HTTPONLY = True
SESSION_COOKIE_SECURE = True
CSRF_COOKIE_SECURE = True#当前仅在Django的Dev分支中.
SESSION_EXPIRE_AT_BROWSER_CLOSE = True
# mysite.utilities.decorators.py import settings def HTTPS_Response(request, URL): if settings.SERVER_TYPE == "DEV": new_URL = URL else: absolute_URL = request.build_absolute_uri(URL) new_URL = "https%s" % absolute_URL[4:] return HttpResponseRedirect(new_URL) # views.py def show_items(request): if request.method == 'POST': newURL = handle_post(request) return HTTPS_Response(request, newURL) # replaces HttpResponseRedirect() else: # request.method == 'GET' theForm = handle_get(request) csrfContext = RequestContext(request, {'theForm': theForm,}) return render_to_response('item-search.html', csrfContext) def handle_post(request): URL = reverse('item-found') # name of view in urls.py item = request.REQUEST.get('item') full_URL = '%s?item=%s' % (URL, item) return full_URL
请注意,这是有可能重新写HTTPS_Response()
为装饰.优点是 - 无需完成所有代码并替换HttpResponseRedirect()
.缺点 - 你必须把装饰器HttpResponseRedirect()
放在Django的前面django.http.__init__.py
.我不想修改Django的代码,但这取决于你 - 这肯定是一个选择.
如果你把你的整个网站都放在https后面,你就不必在django端担心了.(假设您不需要在nginx和django之间保护您的数据,仅在用户和您的服务器之间)