2013-10-25 7 views
2

У меня есть сайт Django по адресу http://example.com, который отлично работает, включая почтовые запросы. Я добавил HTTPS, поэтому мой сайт доступен и по адресу https://example.com.Почему CSRF Django не работает над HTTPS?

Я могу загрузить любую страницу на HTTPS, но я всегда получаю ошибки проверки CSRF при попытке POST. Запросы POST работают нормально на HTTP.

Мой процесс Django работает с стрельбой позади nginx, и у меня есть настройка nginx X_Forwarded_For. Таким образом, запрос HTTPS имеет следующие заголовки (взятые из request.META):

'HTTP_ACCEPT': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', 
'HTTP_ACCEPT_ENCODING': 'gzip, deflate', 
'HTTP_ACCEPT_LANGUAGE': 'en-US,en;q=0.5', 
'HTTP_CONNECTION': 'close', 
'HTTP_COOKIE': 'redacted', 
'HTTP_HOST': 'example.com:80', 
'HTTP_REFERER': 'https://example.com/user/delete/49/', 
'HTTP_USER_AGENT': 'Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0', 
'HTTP_X_FORWARDED_FOR': '1.2.3.4, 192.168.252.22', 
'HTTP_X_FORWARDED_PROTO': 'https', 
'HTTP_X_REAL_IP': '1.2.3.4', 

и запрос HTTP имеет следующие заголовки:

'HTTP_ACCEPT': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', 
'HTTP_ACCEPT_ENCODING': 'gzip, deflate', 
'HTTP_ACCEPT_LANGUAGE': 'en-US,en;q=0.5', 
'HTTP_CONNECTION': 'close', 
'HTTP_COOKIE': 'redacted', 
'HTTP_HOST': 'example.com.com:80', 
'HTTP_USER_AGENT': 'Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0', 
'HTTP_X_FORWARDED_FOR': '1.2.3.4, 192.168.252.22', 
'HTTP_X_FORWARDED_PROTO': 'http', 
'HTTP_X_REAL_IP': '1.2.3.4', 

Почему не CSRF работа по протоколу HTTPS, когда у меня нет проблемы с HTTP?

ответ

7

Оказывается, это была проблема конфигурации nginx. Моя установка сервера:

Nginx -> Nginx -> gunicorn

На второй системе Nginx, я имел

proxy_set_header  Host   $host:$server_port; 

Однако, поскольку HTTPS завершается на первом Nginx, $server_port всегда было 80 .

На HTTPS, Django does strict referer checking (см. Пункт 4). Глядя на источник Джанго:

good_referer = 'https://%s/' % request.get_host() 
if not same_origin(referer, good_referer): 
    reason = REASON_BAD_REFERER % (referer, good_referer) 
    logger.warning('Forbidden (%s): %s', reason, request.path, 
     extra={ 
      'status_code': 403, 
      'request': request, 
     } 
    ) 
    return self._reject(request, reason) 

проверка CSRF терпел неудачу, потому что "https://example.com/" != "https://example.com:80/".

+6

что такое решение? – electropoet

0

Если посмотреть на реализацию CsrfViewMiddleware

Джанго проверяет заголовок 'Referer', когда request.is_secure()

good_referer = 'https://%s/' % request.get_host() 
if not same_origin(referer, good_referer): 
    reason = REASON_BAD_REFERER % (referer, good_referer) 
    return self._reject(request, reason) 
+0

Каково решение? – electropoet

Смежные вопросы