Как развернуть сайт только HTTPS, с Django / nginx?
мой первоначальный вопрос был как включить HTTPS для страницы входа Django, и единственный ответ, рекомендуется, что я - сделать весь сайт только HTTPS.
учитывая, что я использую Django 1.3 и nginx, каков правильный способ сделать сайт только HTTPS?
один упомянутый ответ промежуточного решения, но с оговоркой:
Django не может выполнить перенаправление SSL при сохранении POST данные. Структурируйте свои представления так, чтобы перенаправления происходили только во время GETs.
вопрос по ошибке сервера о переписывание nginx на https, также упоминались проблемы с сообщениями, теряющими данные, и я недостаточно знаком с nginx, чтобы определить, насколько хорошо работает решение.
и рекомендация EFF перейти только HTTPS указано следующее:
приложение должно установить атрибут Secure в файле cookie, когда установив его. Этот атрибут указывает браузеру отправить файл cookie только через безопасный (HTTPS) транспорт, никогда небезопасный (HTTP).
есть ли у приложений, таких как Django-auth, возможность устанавливать куки как безопасные? Или мне нужно написать больше промежуточного ПО?
Итак, каков наилучший способ настроить комбинацию Django/nginx для реализации HTTPS-only, с точки зрения:
- безопасность
- сохранение данных POST
- печенье надлежащим образом
- взаимодействие с другими приложениями Django (такими как Django-auth), работает правильно
- любые другие вопросы, которых я не знаю :)
редактировать - еще одна проблема, которую я только что обнаружил, при тестировании нескольких браузеров. Скажем, у меня есть URL https://mysite.com/search/
, который имеет форму поиска / кнопку. Я нажимаю кнопку, обрабатываю форму в Django, как обычно, и делаю Django HttpResponseRedirect to http://mysite.com/search?results="foo"
. Nginx перенаправляет это на https://mysite.com/search?results="foo"
, как хотелось бы.
однако-Opera имеет видимый вспышка когда происходит перенаправление. И это происходит каждый поиск, даже для одного и того же поискового термина (я думаю, https действительно не кэширует :) хуже, когда я тестирую его в IE, я сначала получаю сообщение:
вы собираетесь быть перенаправлены на соединение, которое не является безопасным-продолжить?
после нажатия кнопки " да " сразу же следует:
вы собираетесь просматривать страницы через безопасное соединение - продолжать?
хотя второе предупреждение IE имеет возможность отключить его -первый предупреждение не делает, поэтому каждый раз, когда кто-то выполняет поиск и перенаправляется на страницу результатов, они получают по крайней мере одно предупреждающее сообщение.
3 ответов
для 2-й части ответа Джона C и Django 1.4+...
вместо расширения HttpResponseRedirect, вы можете изменить request.scheme
to 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
префикс. (По крайней мере те, в результате HttpResponseRedirect()
). В сочетании, похоже, работает хорошо - насколько я могу судить, клиентский браузер никогда не видит http
страница, которую пользователи не вводили в самих.
Часть первая, конфигурация nginx
# 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;
}
}
Часть вторая A, различные безопасные настройки cookie, от settings.py
SERVER_TYPE = "DEV"
SESSION_COOKIE_HTTPONLY = True
SESSION_COOKIE_SECURE = True
CSRF_COOKIE_SECURE = True # в настоящее время только в ветке Dev Django.
SESSION_EXPIRE_AT_BROWSER_CLOSE = True
Часть вторая B, Код Джанго
# 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, только между пользователями и вашим сервером)