Skydda din webbplats från ett mycket vanligt säkerhetshål med Djangos inbyggda CSRF-hantering.
Django är ett Python-webbramverk som du kan använda för att bygga säkra webbapplikationer. Den erbjuder många funktioner för att hjälpa utvecklare med säkerhet. En av dessa funktioner är CSRF-tokens, viktiga för att skydda formulär från Cross-Site Request Forgery-attacker.
Vad är en CSRF-token?
En CSRF-token är en säkerhetsfunktion som skyddar webbapplikationer från Cross-Site Request Forgery (CSRF) attacker. Det låter applikationsservern kontrollera om ett formulär kom från en autentisk webbläsare eller om en hackare har förfalskat det.
CSRF-tokens är formulärinmatningar som håller reda på en användarsession. En webbplats webbapplikationsramverk på serversidan genererar vanligtvis CSRF-tokens för varje unik användarsession. Servern kontrollerar om token är korrekt när en användare skickar ett formulär. CSRF-tokens består i allmänhet av slumpmässiga strängar och siffror, vilket gör deras värden oförutsägbara.
Generering av CSRF-token i Django
Djangos get_token() funktionen genererar slumpmässigt CSRF-tokens. För att hitta den här funktionen, navigera till csrf.py fil i din Python virtuell miljö. Mappstrukturen ska se ut så här:
env/
└── Lib/
└── webbplats-paket/
└── django/
└── middleware/
└── csrf.py
Inuti den här filen hittar du get_token() funktion, som returnerar token. Django använder datamaskering för att skydda tokens värde från hackare.
Som standard aktiverar Django CSRF-skydd för din webbplats genom att lägga till django.middleware.csrf. CsrfViewMiddleware i MEDELVERK lista över dina settings.py fil. Allt du behöver göra är att lägga till {% csrf_token %} till din POSTA formulär. Utan att lägga till {% csrf_token %}, du kommer att få en 403 (förbjudet) fel när du skickar ett formulär.
När du lägger till {% csrf_token %} i ditt formulär skapar den automatiskt ett dolt inmatningsfält med namnet csrfmiddlewaretoken, som innehåller värdet för den maskerade CSRF-token. Servern använder detta värde för att avgöra om formuläret är giltigt. Du kan kontrollera värdet på detta dolda fält genom att visa sidkällan eller använda webbläsarens funktion för utvecklarverktyg.
Hur CSRF-tokens fungerar i Django
När du startar din webbplats med formuläret skapar Django automatiskt en webbläsarcookie kallad csrftoken. Denna cookie håller reda på användaraktivitet på webbplatsen och identifierar varje användare unikt.
När användaren skickar in formuläret jämför servern värdet på kakan med värdet på csrfmiddlewaretoken i det dolda inmatningsfältet. Om dessa värden matchar kommer servern att bearbeta formuläret, annars kommer det att ge ett fel.
Vid första anblicken, värdena för kakan och csrfmiddlewaretoken verkar vara annorlunda. Detta är avsiktligt och lägger till ett extra lager av skydd till CSRF-token. CSRF-token jämförs med cookien så här:
- De get_token() funktionen maskerar CSRF-token innan den skickas vidare till inmatningsfältet.
- När formuläret skickas avmaskeras CSRF-tokenen med hjälp av den hemliga nyckeln i inställningsfilen.
- Den omaskerade token jämförs med sessionskakan.
- Om värdena är desamma bearbetas formuläret. Om inte, returnerar servern ett fel.
För att förhindra hackare från att stjäla din CSRF-token, förnyar Django den varje gång den startar en användarsession.
Skapa anpassade CSRF-tokens
Även om Django gör det enkelt att skydda dina formulär genom att helt enkelt lägga till {% csrf_token %}, att generera CSRF-tokens och lägga till dem manuellt i dina formulär är också möjligt. För att göra detta, importera get_token() fungera:
från django.middleware.csrf importera get_token
Enligt din åsikt kan du generera CSRF-token så här:
defview_name(begäran):
csrf_token = get_token (begäran)# utför visningslogik
sammanhang = {
"csrf_token": csrf_token
}
lämna tillbaka rendera (begäran, 'app_name/template.html', sammanhang=kontext)
I din HTML-mall kan du manuellt inkludera din input-tagg och lägga till csrf_token till det så här:
<formmetod="POSTA" >
<inmatningtyp="dold"namn="csrfmiddlewaretoken"värde="{{ csrf_token }}">
{{form.as_p}}
<knapptyp="Skicka in"klass="btn btn-outline-sekundär">Lägg till bokknapp>
form>
Alternativt kan du skapa det dolda inmatningsfältet från dina vyer så här:
defdin åsikt(begäran):
csrf_token = get_token (begäran)
csrf_token_html = ''.format (csrf_token)# utför visningslogik
sammanhang = {
"csrf_token": csrf_token_html
}
lämna tillbaka rendera (begäran, 'app_name/template.html', sammanhang=kontext)
Du kan sedan lägga till den i din HTML-mall så här:
<formmetod="POSTA" >
{{ csrf_token_html|safe }}
{{form.as_p}}
<knapptyp="Skicka in"klass="btn btn-outline-sekundär">Lägg till bokknapp>
form>
Om du helt vill kontrollera ditt formulärs CSRF-skydd kan du göra det genom att jämföra din CSRF-token med cookien som lagras i webbläsaren. Baserat på resultatet av jämförelsen kan du hantera formulärinlämningen hur du vill. Här är ett exempel:
från django.shortcuts importera framställa
från django.middleware.csrf importera get_token, _unmask_cipher_token
från django.utils.crypto importera konstant_tid_jämfördefdin åsikt(begäran):
# Generera en anpassad CSRF-token
csrf_token = get_token (begäran)
csrf_cookie = begäran. COOKIES.get('csrftoken')# avmaskera csrf-token
unmasked_csrf_token = _unmask_cipher_token (csrf_token)
# Jämför polletterna
ominte constant_time_compare (unmasked_csrf_token, csrf_cookie):
# Hantera fallet där polletterna inte matchar
passera
annan:
# Hantera fallet där polletterna matchar
passera
# Återge mallen
sammanhang = {
'csrf_token': csrf_token,
}
lämna tillbaka rendera (begäran, 'app_name/template.html', sammanhang=kontext)
Det här kodavsnittet hämtar csrf_cookie från HTTP-förfrågningsobjektet. Den använder sedan _unmask_cipher_token() funktion för att avmaska csrf_token.
Ett villkorligt uttalande jämför värdena för det hämtade csrf_cookie och de omaskerade csrf_token. Denna jämförelse använder konstant_tid_jämför funktion för att skydda mot tidsexploateringar. Du kan skriva din logik baserat på resultatet av jämförelsen.
Inaktiverar CSRF-skydd i Django
Även om Django gör en standardbestämmelse för CSRF-skydd, kan du inaktivera det i ditt projekt om du vill. Det finns två sätt att göra detta:
- Inaktivera CSRF-skydd på hela din webbplats.
- Inaktiverar CSRF-skydd på en specifik vy.
Inaktivera CSRF-skydd på hela din webbplats
För att inaktivera Djangos CSRF-skydd på din webbplats måste du helt enkelt ta bort CSRF-mellanvaran från din inställningsfil. I din inställningsfil, leta reda på en lista som heter MEDELVERK. Inuti listan, sök efter detta:
'django.middleware.csrf. CsrfViewMiddleware',
När du har hittat det bör du ta bort det från din kod för att Djangos standard CSRF-skydd ska inaktivera det.
Inaktivera CSRF-skydd på en specifik vy
Om du bara vill inaktivera CSRF-skydd på en specifik Django-vy, använd @csrf_exempt dekoratör. Här är ett kodavsnitt för att demonstrera:
från django.views.decorators.csrf importera csrf_exempt
@csrf_exempt
defview_name(begäran):
# utför visningslogik
passera
De @csrf_exempt decorator är bara en av flera relaterade till CSRF-skydd i Django. Du kan läsa om resten på Djangos CSRF-referens.
Inaktivera inte CSRF-skydd på din webbplats
Även om Django gör det möjligt, rekommenderas inte att inaktivera Djangos inbyggda CSRF-skyddsmekanism. Om du gör det kommer din webbplats att bli sårbar för CSRF-attacker och i slutändan påverka användarna av din app negativt.
Om du inte är en erfaren utvecklare som vet hur man implementerar en anpassad CSRF-skyddsmekanism, bör du arbeta med alternativet från Django.