我原来的问题是如何启用HTTPS的Django的login页面 ,唯一的回应,build议我 – 使整个网站只有HTTPS 。
鉴于我正在使用Django 1.3和nginx,有什么正确的方法,使网站HTTPS的?
一个响应提到了一个中间件解决scheme ,但有一个警告:
Django在维护POST数据时不能执行SSLredirect。 请构build您的意见,使redirect只发生在GET。
关于nginx重写为https的服务器故障的一个问题,也提到了POSTs丢失数据的问题,而且我对nginx不够熟悉,无法确定解决scheme的效果。
而EFF的build议是仅使用HTTPS ,注意到:
设置时,应用程序必须在Cookie上设置“安全”属性。 该属性指示浏览器仅通过安全(HTTPS)传输发送cookie,从不安全(HTTP)。
像Django-auth这样的应用程序能够将cookies设置为Secure? 还是我必须写更多的中间件?
那么,什么是configurationDjango / nginx的组合来实现仅HTTPS的最佳方式,具体如下:
编辑 – 我刚刚发现的另一个问题,同时testing多个浏览器。 说我有urlhttps://mysite.com/search/
,它有一个search表单/button。 我点击button,像往常一样在Django中处理表单,然后执行Django HttpResponseRedirect到http://mysite.com/search?results="foo"
。 Nginx根据需要将它redirect到https://mysite.com/search?results="foo"
。
但是 – Operaredirect发生时,Opera具有可见的闪存 。 它发生每一个search,即使对于相同的search术语(我猜https实际上不caching:)更糟糕的是,当我在IE中testing它时,我首先得到的消息:
您即将被redirect到一个不安全的连接 – 继续?
点击“是”之后,紧接着是:
您即将通过安全连接查看网页 – 继续?
虽然第二个IE警告有一个选项可以closures – 第一个警告不会,所以每次有人进行search并被redirect到结果页面时,他们至less会收到一条警告消息。
对于约翰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代码处理具有http
前缀的内部 URL生成。 (至少,从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 =真
SESSION_COOKIE_SECURE =真
CSRF_COOKIE_SECURE = True#目前只在Django的Dev分支。
SESSION_EXPIRE_AT_BROWSER_CLOSE =真
# 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()
。 缺点 – 你必须把装饰器放在django.http.__init__.py
Django中的HttpResponseRedirect()
django.http.__init__.py
。 我不想修改Django的代码,但这取决于你自己 – 这当然是一个选择。
如果你坚持你的整个网站后面的https,你不需要担心它在Django结束。 (假设你不需要保护nginx和django之间的数据,只能在用户和你的服务器之间)