Proteggi i tuoi cookie
In settings.py inserisci le righe
SESSION_COOKIE_SECURE = True
CSRF_COOKIE_SECURE = True
e i cookie verranno inviati solo tramite le connessioni HTTPS. Inoltre, probabilmente vuoi anche SESSION_EXPIRE_AT_BROWSER_CLOSE=True
. Nota se stai usando versioni precedenti di django (meno di 1.4), non c'è un'impostazione per i cookie CSRF sicuri. Come soluzione rapida, puoi semplicemente rendere sicuro il cookie CSRF quando il cookie di sessione è sicuro ( SESSION_COOKIE_SECURE=True
), modificando django/middleware/csrf.py
:
class CsrfViewMiddleware(object):
...
def process_response(self, request, response):
...
response.set_cookie(settings.CSRF_COOKIE_NAME,
request.META["CSRF_COOKIE"], max_age = 60 * 60 * 24 * 7 * 52,
domain=settings.CSRF_COOKIE_DOMAIN,
secure=settings.SESSION_COOKIE_SECURE or None)
Richieste HTTP dirette a HTTPS nel server web
Successivamente vuoi una regola di riscrittura che reindirizzi le richieste http a https, ad es. in nginx
server {
listen 80;
rewrite ^(.*) https://$host$1 permanent;
}
La funzione reverse
di Django e i tag modello url restituiscono solo collegamenti relativi; quindi se sei su una pagina https i tuoi link ti terranno sul sito https.
Imposta la variabile ambientale del sistema operativo HTTPS su
Infine, (e la mia risposta originale l'ha escluso), è necessario abilitare la variabile ambientale del sistema operativo HTTPS
in 'on'
, quindi django farà precedere https ai collegamenti generati completamente (ad esempio, come con HttpRedirectRequest
s). Se stai utilizzando mod_wsgi, puoi aggiungere la riga:
os.environ['HTTPS'] = "on"
al tuo script wsgi . Se stai utilizzando uwsgi, puoi aggiungere una variabile ambientale tramite l'interruttore della riga di comando --env HTTPS=on
o aggiungendo la riga env = HTTPS=on
al tuo file uwsgi .ini
. Come ultima risorsa, se non funziona nient'altro, puoi modificare il tuo file delle impostazioni per avere le righe import os
e os.environ['HTTPS'] = "on"
, che dovrebbe funzionare anche.
Se stai usando wsgi, potresti voler impostare ulteriormente la variabile ambientale wsgi.url_scheme
in 'https'
aggiungendo questo al tuo settings.py
:
os.environ['wsgi.url_scheme'] = 'https'
Il consiglio wsgi per gentile concessione di commento di Vijayendra Bapte .
Puoi vedere la necessità di questa variabile ambientale leggendo django/http/__init__.py
:
def build_absolute_uri(self, location=None):
"""
Builds an absolute URI from the location and the variables available in
this request. If no location is specified, the absolute URI is built on
''request.get_full_path()''.
"""
if not location:
location = self.get_full_path()
if not absolute_http_url_re.match(location):
current_uri = '%s://%s%s' % (self.is_secure() and 'https' or 'http',
self.get_host(), self.path)
location = urljoin(current_uri, location)
return iri_to_uri(location)
def is_secure(self):
return os.environ.get("HTTPS") == "on"
Altre cose del server Web:
Prendi i consigli di quel ragazzo e attiva le intestazioni HSTS nel tuo server web aggiungendo una riga a nginx:
add_header Strict-Transport-Security max-age=31536000;
Questo indica al tuo browser web che il tuo sito web per i prossimi 10 anni utilizzerà solo HTTPS. Se c'è un attacco Man-in-the-middle su qualsiasi visita futura dallo stesso browser (ad esempio, si accede a un router malevolo in una caffetteria che reindirizza a una versione HTTP della pagina), il browser si ricorderà dovrebbe essere solo HTTPS e impedirti di rinunciare inavvertitamente alle tue informazioni. Ma fai attenzione a questo, non puoi cambiare idea e in seguito decidere che parte del tuo dominio verrà servita su HTTP (fino a quando sono trascorsi 10 anni dalla rimozione di questa riga). Quindi pianificare in anticipo; ad es., se ritieni che la tua applicazione possa presto diventare popolare e dovrai trovarti su un CDN di grandi dimensioni che non gestisce bene HTTPS a un prezzo che ti puoi permettere, potresti avere un problema.
Assicurati anche di disabilitare i protocolli deboli. Invia il tuo dominio a un Test SSL per verificare potenziali problemi (chiave troppo corta, non utilizzando TLSv1.2, utilizzando protocolli non funzionanti, eccetera.). Ad esempio, in nginx io uso:
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_ciphers "EECDH+ECDSA+AESGCM EECDH+aRSA+AESGCM EECDH+ECDSA+SHA384 EECDH+ECDSA+SHA256 EECDH+aRSA+SHA384 EECDH+aRSA+SHA256 EECDH+aRSA+RC4 EECDH EDH+aRSA RC4 !aNULL !eNULL !LOW !3DES !MD5 !EXP !PSK !SRP !DSS";