We recently upgraded one of our e-commerce websites to Django 1.4 and were
pleased to find the new
SECURE_PROXY_SSL_HEADER
setting.
Our server is using nginx to proxy requests to Apache which serves the Django
project. Therefore, Apache/Django is not aware of when incoming requests are
on https. The HttpRequest.is_secure() will always return False. That means
any decorators or middleware which redirect a view to a secure URL will result
in an infinite redirect loop.
The solution is:
-
Have the proxy server (nginx in our case) set the
X-Forwarded-ProtocolHTTP header. In the nginx config:proxy_set_header X-Forwarded-Protocol $scheme; -
Tell Django to use the
X-Forwarded-ProtocolHTTP header to determine if the request is secure. We defineSECURE_PROXY_SSL_HEADERinsettings.py:SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTOCOL', 'https')
The way that works is nginx will set X-Forwarded-Protocol to "http" on normal
connections and "https" on secure connections. Django's HttpRequest.is_secure()
method will return True when it's set to "https".
Make sure you read the security warning for SECURE_PROXY_SSL_HEADER if you're goingn to use it.
