CSRF Protection
La protezione CSRF (Cross-Site Request Forgery) eâ una delle funzionalitaâ di sicurezza piuâ importanti di Django. Un attacco CSRF avviene quando un sito malevolo induce il browser di un utente autenticato a inviare richieste non autorizzate verso un altro sito. Django previene questo tipo di attacco utilizzando un sistema basato su token.
Cosâeâ un Attacco CSRF
In un attacco CSRF, un aggressore crea una pagina web contenente un form nascosto che punta al tuo sito. Se un utente autenticato visita quella pagina, il form viene inviato automaticamente, eseguendo azioni non desiderate con le credenziali dellâutente. Ad esempio, un trasferimento bancario o un cambio di password.
CsrfViewMiddleware
Django include il CsrfViewMiddleware che verifica automaticamente la presenza e la validitaâ di un token CSRF in tutte le richieste POST, PUT, PATCH e DELETE.
# settings.py
MIDDLEWARE = [
# ...
'django.middleware.csrf.CsrfViewMiddleware',
# ...
]
Questo middleware genera un token unico per ogni sessione utente e verifica che le richieste di modifica contengano un token valido.
Il Template Tag csrf_token
Per includere il token CSRF nei form HTML, Django mette a disposizione il template tag {% csrf_token %}. Questo tag deve essere inserito allâinterno di ogni form che utilizza il metodo POST.
# template.html
# <form method="post" action="/invia/">
# {% csrf_token %}
# <input type="text" name="messaggio">
# <button type="submit">Invia</button>
# </form>
Il tag genera un campo nascosto nel form contenente il token:
# Output HTML generato:
# <input type="hidden" name="csrfmiddlewaretoken"
# value="abc123tokenLungoECasuale">
Decoratori per il Controllo CSRF
Django fornisce decoratori per personalizzare il comportamento della protezione CSRF su singole view.
@csrf_exempt
Disabilita la verifica CSRF per una specifica view. Da usare con estrema cautela e solo quando strettamente necessario, ad esempio per endpoint che ricevono richieste da servizi esterni.
from django.views.decorators.csrf import csrf_exempt
from django.http import JsonResponse
@csrf_exempt
def webhook_esterno(request):
if request.method == 'POST':
dati = request.body
# Elabora i dati dal servizio esterno
return JsonResponse({'stato': 'ricevuto'})
@csrf_protect
Forza la verifica CSRF su una view specifica, anche se il middleware globale eâ stato disabilitato. Utile per proteggere view critiche.
from django.views.decorators.csrf import csrf_protect
@csrf_protect
def modifica_profilo(request):
if request.method == 'POST':
# Questa view e' sempre protetta da CSRF
request.user.nome = request.POST['nome']
request.user.save()
return redirect('profilo')
CSRF nelle Richieste AJAX
Quando si effettuano richieste AJAX (ad esempio con JavaScript Fetch API o librerie come Axios), il token CSRF deve essere incluso manualmente nellâheader della richiesta.
Leggere il Token dal Cookie
Django salva il token CSRF in un cookie chiamato csrftoken. Puoi leggerlo con JavaScript e includerlo nellâheader X-CSRFToken.
# Funzione JavaScript per ottenere il cookie CSRF
# function getCookie(name) {
# let cookieValue = null;
# if (document.cookie && document.cookie !== '') {
# const cookies = document.cookie.split(';');
# for (let cookie of cookies) {
# cookie = cookie.trim();
# if (cookie.startsWith(name + '=')) {
# cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
# break;
# }
# }
# }
# return cookieValue;
# }
#
# const csrftoken = getCookie('csrftoken');
#
# fetch('/api/endpoint/', {
# method: 'POST',
# headers: {
# 'Content-Type': 'application/json',
# 'X-CSRFToken': csrftoken,
# },
# body: JSON.stringify({ dato: 'valore' }),
# });
Configurazione del Cookie CSRF
Puoi personalizzare il comportamento del cookie CSRF nelle impostazioni:
# settings.py
# Nome del cookie CSRF
CSRF_COOKIE_NAME = 'csrftoken'
# Durata del cookie in secondi (default: 1 anno)
CSRF_COOKIE_AGE = 31449600
# Invia il cookie solo su HTTPS
CSRF_COOKIE_SECURE = True
# Impedisce l'accesso al cookie da JavaScript (default: False)
CSRF_COOKIE_HTTPONLY = False
# Domini fidati per richieste cross-site
CSRF_TRUSTED_ORIGINS = [
'https://miosito.com',
'https://app.miosito.com',
]
Conclusione
La protezione CSRF di Django eâ un meccanismo essenziale per la sicurezza delle applicazioni web. Utilizzare correttamente il template tag {% csrf_token %} nei form, gestire il token nelle richieste AJAX tramite lâheader X-CSRFToken e configurare adeguatamente le impostazioni del cookie CSRF sono pratiche fondamentali per prevenire attacchi di falsificazione delle richieste.