J’essaie de tester mon application Django localement en utilisant SSL. J’ai une vue avec le décorateur @login_required
. Donc, quand je frappe /locker
, je suis redirigé vers /locker/login?next=/locker
. Cela fonctionne bien avec http.
Cependant, chaque fois que j’utilise https, la redirection perd en quelque sorte la connexion sécurisée, donc je reçois quelque chose comme https://cumulus.dev/locker -> http://cumulus.dev/locker/login?next=/locker
Si je vais directement sur https://cumulus.dev/locker/login?next=locker
la page s’ouvre bien sur une connexion sécurisée. Mais une fois que je saisis le nom d’utilisateur et le mot de passe, je retourne à http://cumulus.dev/locker
.
J’utilise Nginx pour gérer le SSL, qui parle ensuite à runserver
. Mon nginx config est
upstream app_server_djangoapp { server localhost:8000 fail_timeout=0; } server { listen 80; server_name cumulus.dev; access_log /var/log/nginx/cumulus-dev-access.log; error_log /var/log/nginx/cumulus-dev-error.log info; keepalive_timeout 5; # path for static files root /home/gaurav/www/Cumulus/cumulus_lightbox/static; location / { proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $http_host; proxy_redirect off; if (!-f $request_filename) { proxy_pass http://app_server_djangoapp; break; } } } server { listen 443; server_name cumulus.dev; ssl on; ssl_certificatee /etc/ssl/cacert-cumulus.pem; ssl_certificatee_key /etc/ssl/privkey.pem; access_log /var/log/nginx/cumulus-dev-access.log; error_log /var/log/nginx/cumulus-dev-error.log info; keepalive_timeout 5; # path for static files root /home/gaurav/www/Cumulus/cumulus_lightbox/static; location / { proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Ssl on; proxy_set_header Host $http_host; proxy_redirect off; if (!-f $request_filename) { proxy_pass http://app_server_djangoapp; break; } } }
Django s’exécute sur HTTP uniquement derrière le proxy, il l’utilisera donc toujours pour construire des URL absolues (telles que les redirections), à moins que vous ne configuriez la façon dont la requête mandatée a été créée sur HTTPS.
A partir de Django 1.4, vous pouvez le faire en utilisant le paramètre SECURE_PROXY_SSL_HEADER
. Lorsque Django voit l’en-tête configuré, il traitera la demande comme HTTPS au lieu de HTTP: request.is_secure()
retournera true, https://
URL seront générées, etc.
Toutefois, notez les avertissements de sécurité dans la documentation: vous devez vous assurer que le proxy remplace ou supprime l’en-tête approuvé de toutes les demandes client entrantes, à la fois HTTP et HTTPS. Votre configuration nginx ci-dessus ne fait pas cela avec X-Forwarded-Ssl
, ce qui la rend falsifiable.
Une solution classique consiste à définir le X-Forwarded-Protocol
sur http
ou https
, selon le cas, dans chacune de vos configurations de proxy. Ensuite, vous pouvez configurer Django pour le rechercher en utilisant:
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTOCOL', 'https')