Lösenordshantering i DjangoLink to this heading

Lösenordshantering är något som i allmänhet inte bör uppfinnas på nytt i onödan, och Django strävar efter att tillhandahålla en säker och flexibel uppsättning verktyg för hantering av användarlösenord. Detta dokument beskriver hur Django lagrar lösenord, hur hashningen av lagringen kan konfigureras och några verktyg för att arbeta med hashade lösenord.

Hur Django lagrar lösenordLink to this heading

Django tillhandahåller ett flexibelt system för lagring av lösenord och använder PBKDF2 som standard.

Attributet password för ett User-objekt är en sträng i detta format:

Text
<algorithm>$<iterations>$<salt>$<hash>

Dessa är de komponenter som används för att lagra en användares lösenord, separerade med dollartecknet och består av: hashingalgoritmen, antalet algoritmiterationer (arbetsfaktor), det slumpmässiga saltet och den resulterande lösenordshashen. Algoritmen är en av ett antal envägs hash- eller lösenordslagringsalgoritmer som Django kan använda, se nedan. Iterationer beskriver hur många gånger algoritmen körs över hashen. Salt är det slumpmässiga frö som används och hashen är resultatet av envägsfunktionen.

Som standard använder Django PBKDF2-algoritmen med en SHA256-hash, en mekanism för lösenordsträckning som rekommenderas av NIST. Detta bör vara tillräckligt för de flesta användare: det är ganska säkert och kräver enorma mängder datatid för att bryta.

Beroende på dina krav kan du dock välja en annan algoritm eller till och med använda en anpassad algoritm för att matcha din specifika säkerhetssituation. Återigen, de flesta användare ska inte behöva göra det här - om du inte är säker behöver du förmodligen inte göra det. Om du gör det, läs vidare:

Django väljer vilken algoritm som ska användas genom att konsultera inställningen PASSWORD_HASHERS. Detta är en lista över hashingalgoritmklasser som denna Django-installation stöder.

För att lagra lösenord kommer Django att använda den första hashern i PASSWORD_HASHERS. För att lagra nya lösenord med en annan algoritm, sätt din föredragna algoritm först i PASSWORD_HASHERS.

För att verifiera lösenord kommer Django att hitta den hasher i listan som matchar algoritmnamnet i det lagrade lösenordet. Om ett lagrat lösenord namnger en algoritm som inte finns i PASSWORD_HASHERS, kommer försök att verifiera det att ge upphov till ValueError.

Standardvärdet för PASSWORD_HASHERS är:

Code
PASSWORD_HASHERS = [
    "django.contrib.auth.hashers.PBKDF2PasswordHasher",
    "django.contrib.auth.hashers.PBKDF2SHA1PasswordHasher",
    "django.contrib.auth.hashers.Argon2PasswordHasher",
    "django.contrib.auth.hashers.BCryptSHA256PasswordHasher",
    "django.contrib.auth.hashers.ScryptPasswordHasher",
]

Detta innebär att Django kommer att använda PBKDF2 för att lagra alla lösenord men kommer att stödja kontroll av lösenord som lagras med PBKDF2SHA1, argon2 och bcrypt.

I de följande avsnitten beskrivs ett par vanliga sätt som avancerade användare kan vilja ändra den här inställningen på.

Använda Argon2 med DjangoLink to this heading

Argon2 är vinnaren av 2015 års Password Hashing Competition, en öppen tävling som anordnas av en gemenskap för att välja nästa generations hashingalgoritm. Den är utformad för att inte vara lättare att beräkna på anpassad hårdvara än den är att beräkna på en vanlig CPU. Standardvarianten för Argon2-lösenordshashern är Argon2id.

Argon2 är inte standard för Django eftersom det kräver ett tredjepartsbibliotek. Tävlingspanelen för lösenordshashing rekommenderar dock omedelbar användning av Argon2 snarare än de andra algoritmerna som stöds av Django.

Gör så här om du vill använda Argon2id som standardalgoritm för lagring:

  1. Installera paketet argon2-cffi. Detta kan göras genom att köra python -m pip install django[argon2], vilket är likvärdigt med python -m pip install argon2-cffi (tillsammans med eventuella versionskrav från Djangos pyproject.toml).

  2. Ändra PASSWORD_HASHERS till att lista Argon2PasswordHasher först. Det vill säga, i din inställningsfil skulle du skriva:

    Code
    PASSWORD_HASHERS = [
        "django.contrib.auth.hashers.Argon2PasswordHasher",
        "django.contrib.auth.hashers.PBKDF2PasswordHasher",
        "django.contrib.auth.hashers.PBKDF2SHA1PasswordHasher",
        "django.contrib.auth.hashers.BCryptSHA256PasswordHasher",
        "django.contrib.auth.hashers.ScryptPasswordHasher",
    ]
    

    Behåll och/eller lägg till poster i den här listan om du vill att Django ska uppgradera lösenord.

Använda bcrypt med DjangoLink to this heading

Bcrypt är en populär algoritm för lagring av lösenord som är särskilt utformad för långvarig lagring av lösenord. Det är inte den standard som används av Django eftersom det kräver användning av tredjepartsbibliotek, men eftersom många människor kanske vill använda det stöder Django bcrypt med minimal ansträngning.

Gör så här om du vill använda Bcrypt som standardalgoritm för lagring:

  1. Installera paketet bcrypt. Detta kan göras genom att köra python -m pip install django[bcrypt], vilket är likvärdigt med python -m pip install bcrypt (tillsammans med eventuella versionskrav från Djangos pyproject.toml).

  2. Ändra PASSWORD_HASHERS till att lista BCryptSHA256PasswordHasher först. Det vill säga, i din inställningsfil skulle du skriva:

    Code
    PASSWORD_HASHERS = [
        "django.contrib.auth.hashers.BCryptSHA256PasswordHasher",
        "django.contrib.auth.hashers.PBKDF2PasswordHasher",
        "django.contrib.auth.hashers.PBKDF2SHA1PasswordHasher",
        "django.contrib.auth.hashers.Argon2PasswordHasher",
        "django.contrib.auth.hashers.ScryptPasswordHasher",
    ]
    

    Behåll och/eller lägg till poster i den här listan om du vill att Django ska uppgradera lösenord.

Det var allt - nu kommer din Django-installation att använda Bcrypt som standardlagringsalgoritm.

Använda scrypt med DjangoLink to this heading

scrypt liknar PBKDF2 och bcrypt genom att använda ett bestämt antal iterationer för att sakta ner brute-force-attacker. Men eftersom PBKDF2 och bcrypt inte kräver mycket minne kan angripare med tillräckliga resurser starta storskaliga parallella attacker för att påskynda angreppsprocessen. scrypt är särskilt utformad för att använda mer minne jämfört med andra lösenordsbaserade nyckeldrivningsfunktioner för att begränsa mängden parallellism som en angripare kan använda, se RFC 7914 för mer information.

Gör så här om du vill använda scrypt som standardalgoritm för lagring:

  1. Ändra PASSWORD_HASHERS så att ScryptPasswordHasher listas först. Det vill säga, i din inställningsfil:

    Code
    PASSWORD_HASHERS = [
        "django.contrib.auth.hashers.ScryptPasswordHasher",
        "django.contrib.auth.hashers.PBKDF2PasswordHasher",
        "django.contrib.auth.hashers.PBKDF2SHA1PasswordHasher",
        "django.contrib.auth.hashers.Argon2PasswordHasher",
        "django.contrib.auth.hashers.BCryptSHA256PasswordHasher",
    ]
    

    Behåll och/eller lägg till poster i den här listan om du vill att Django ska uppgradera lösenord.

Ökning av saltets entropiLink to this heading

De flesta lösenordshashar innehåller ett salt tillsammans med sin lösenordshash för att skydda mot regnbågstabellsattacker. Själva saltet är ett slumpmässigt värde som ökar storleken och därmed kostnaden för regnbågstabellen och är för närvarande inställt på 128 bitar med värdet salt_entropy i BasePasswordHasher. I takt med att beräknings- och lagringskostnaderna minskar bör detta värde höjas. När du implementerar din egen lösenordshasher kan du åsidosätta detta värde för att använda en önskad entropinivå för dina lösenordshashar. salt_entropy mäts i bitar.

Ökning av arbetsfaktornLink to this heading

PBKDF2 och bcryptLink to this heading

Algoritmerna PBKDF2 och bcrypt använder ett antal iterationer eller rundor för hashning. Detta gör att angriparna medvetet blir långsammare, vilket försvårar attacker mot hashade lösenord. I takt med att datorkraften ökar måste dock antalet iterationer ökas. Vi har valt en rimlig standard (och kommer att öka den med varje version av Django), men du kanske vill justera den upp eller ner, beroende på dina säkerhetsbehov och tillgänglig processorkraft. För att göra det underklassar du lämplig algoritm och åsidosätter parametern iterations (använd parametern rounds när du underklassar en bcrypt hasher). Till exempel, för att öka antalet iterationer som används av standard PBKDF2-algoritmen:

  1. Skapa en underklass av django.contrib.auth.hashers.PBKDF2PasswordHasher

    Code
    from django.contrib.auth.hashers import PBKDF2PasswordHasher
    
    
    class MyPBKDF2PasswordHasher(PBKDF2PasswordHasher):
        """
        A subclass of PBKDF2PasswordHasher that uses 100 times more iterations.
        """
    
        iterations = PBKDF2PasswordHasher.iterations * 100
    

    Spara detta någonstans i ditt projekt. Till exempel kan du lägga det i en fil som myproject/hashers.py.

  2. Lägg till din nya hasher som den första posten i PASSWORD_HASHERS:

    Code
    PASSWORD_HASHERS = [
        "myproject.hashers.MyPBKDF2PasswordHasher",
        "django.contrib.auth.hashers.PBKDF2PasswordHasher",
        "django.contrib.auth.hashers.PBKDF2SHA1PasswordHasher",
        "django.contrib.auth.hashers.Argon2PasswordHasher",
        "django.contrib.auth.hashers.BCryptSHA256PasswordHasher",
        "django.contrib.auth.hashers.ScryptPasswordHasher",
    ]
    

Det var allt - nu kommer din Django-installation att använda fler iterationer när den lagrar lösenord med PBKDF2.

Argon2Link to this heading

Argon2 har följande attribut som kan anpassas:

  1. time_cost styr antalet iterationer inom hashen.

  2. memory_cost styr storleken på det minne som måste användas under beräkningen av hashen.

  3. parallelism styr hur många CPU:er som beräkningen av hashen kan parallelliseras på.

Standardvärdena för dessa attribut är förmodligen bra för dig. Om du tycker att lösenordshashen är för snabb eller för långsam kan du justera den på följande sätt:

  1. Välj parallellism till det antal trådar som du kan avvara för att beräkna hashen.

  2. Välj memory_cost till det KiB minne som du kan avvara.

  3. Justera time_cost och mät den tid det tar att hasha ett lösenord. Välj en time_cost som tar en acceptabel tid för dig. Om time_cost inställd på 1 är oacceptabelt långsam, sänk memory_cost.

skrypteraLink to this heading

scrypt har följande attribut som kan anpassas:

  1. work_factor styr antalet iterationer inom hashen.

  2. block_storlek

  3. parallelism styr hur många trådar som ska köras parallellt.

  4. maxmem begränsar den maximala storleken på minnet som kan användas under beräkningen av hashen. Standardvärdet är 0, vilket innebär standardbegränsningen från OpenSSL-biblioteket.

Vi har valt rimliga standardvärden, men du kanske vill justera dem uppåt eller nedåt, beroende på dina säkerhetsbehov och tillgänglig processorkraft.

Uppgradering av lösenordLink to this heading

När användare loggar in, om deras lösenord lagras med något annat än den föredragna algoritmen, kommer Django automatiskt att uppgradera algoritmen till den föredragna algoritmen. Detta innebär att gamla installationer av Django automatiskt blir säkrare när användare loggar in, och det innebär också att du kan byta till nya (och bättre) lagringsalgoritmer när de uppfinns.

Django kan dock endast uppgradera lösenord som använder algoritmer som nämns i PASSWORD_HASHERS, så när du uppgraderar till nya system bör du se till att aldrig ta bort poster från den här listan. Om du gör det kommer användare som använder algoritmer som inte nämns inte att kunna uppgradera. Hashade lösenord kommer att uppdateras när antalet PBKDF2-iterationer, bcrypt-rundor eller argon2-attribut ökas (eller minskas).

Tänk på att om alla lösenord i din databas inte är kodade i standardalgoritmen för hasharen, kan du vara sårbar för en tidsattack med uppräkning av användare på grund av en skillnad mellan varaktigheten för en inloggningsbegäran för en användare med ett lösenord som är kodat i en icke-standardalgoritm och varaktigheten för en inloggningsbegäran för en icke-existerande användare (som kör standardalgoritmen för hasharen). Du kanske kan mildra detta genom att uppgradera äldre lösenordshashar.

Lösenordsuppgradering utan krav på inloggningLink to this heading

Om du har en befintlig databas med en äldre, svag hash, t.ex. MD5, kanske du vill uppgradera dessa hashar själv istället för att vänta på att uppgraderingen ska ske när en användare loggar in (vilket kanske aldrig sker om en användare inte återvänder till din webbplats). I det här fallet kan du använda en ”wrappad” lösenordshash.

I det här exemplet migrerar vi en samling MD5-hashar till att använda PBKDF2(MD5(password)) och lägger till motsvarande lösenordshash för att kontrollera om en användare angav rätt lösenord vid inloggning. Vi antar att vi använder den inbyggda User-modellen och att vårt projekt har en accounts-app. Du kan ändra mönstret så att det fungerar med vilken algoritm som helst eller med en anpassad användarmodell.

Först ska vi lägga till den anpassade hasharen:

konton/hashers.py
Python
from django.contrib.auth.hashers import (
    PBKDF2PasswordHasher,
    MD5PasswordHasher,
)


class PBKDF2WrappedMD5PasswordHasher(PBKDF2PasswordHasher):
    algorithm = "pbkdf2_wrapped_md5"

    def encode_md5_hash(self, md5_hash, salt, iterations=None):
        return super().encode(md5_hash, salt, iterations)

    def encode(self, password, salt, iterations=None):
        _, _, md5_hash = MD5PasswordHasher().encode(password, salt).split("$", 2)
        return self.encode_md5_hash(md5_hash, salt, iterations)

Datamigreringen kan se ut ungefär som följer:

konton/migreringar/0002_migrera_md5_lösenord.py
Python
from django.db import migrations

from ..hashers import PBKDF2WrappedMD5PasswordHasher


def forwards_func(apps, schema_editor):
    User = apps.get_model("auth", "User")
    users = User.objects.filter(password__startswith="md5$")
    hasher = PBKDF2WrappedMD5PasswordHasher()
    for user in users:
        algorithm, salt, md5_hash = user.password.split("$", 2)
        user.password = hasher.encode_md5_hash(md5_hash, salt)
        user.save(update_fields=["password"])


class Migration(migrations.Migration):
    dependencies = [
        ("accounts", "0001_initial"),
        # replace this with the latest migration in contrib.auth
        ("auth", "####_migration_name"),
    ]

    operations = [
        migrations.RunPython(forwards_func),
    ]

Tänk på att denna migrering kommer att ta i storleksordningen flera minuter för flera tusen användare, beroende på hastigheten på din maskinvara.

Slutligen lägger vi till en PASSWORD_HASHERS-inställning:

mysite/settings.py
Python
PASSWORD_HASHERS = [
    "django.contrib.auth.hashers.PBKDF2PasswordHasher",
    "accounts.hashers.PBKDF2WrappedMD5PasswordHasher",
]

Inkludera alla andra hashrar som din webbplats använder i den här listan.

Inkluderade hasplarLink to this heading

Den fullständiga listan över hashare som ingår i Django är:

Code
[
    "django.contrib.auth.hashers.PBKDF2PasswordHasher",
    "django.contrib.auth.hashers.PBKDF2SHA1PasswordHasher",
    "django.contrib.auth.hashers.Argon2PasswordHasher",
    "django.contrib.auth.hashers.BCryptSHA256PasswordHasher",
    "django.contrib.auth.hashers.BCryptPasswordHasher",
    "django.contrib.auth.hashers.ScryptPasswordHasher",
    "django.contrib.auth.hashers.MD5PasswordHasher",
]

De motsvarande algoritmnamnen är:

  • pbkdf2_sha256

  • pbkdf2_sha1

  • argon2

  • bcrypt_sha256

  • bcrypt

  • skryptera

  • md5

Skriva din egen haschmaskinLink to this heading

Om du skriver en egen lösenordshash som innehåller en arbetsfaktor, t.ex. ett antal iterationer, bör du implementera metoden harden_runtime(self, password, encoded) för att överbrygga körtidsgapet mellan den arbetsfaktor som anges i det kodade lösenordet och hasherns standardarbetsfaktor. Detta förhindrar en tidsattack för uppräkning av användare på grund av skillnaden mellan en inloggningsbegäran för en användare med ett lösenord som kodats i ett äldre antal iterationer och en icke-existerande användare (som kör standardhasherns standardantal iterationer).

Om vi tar PBKDF2 som exempel och encoded innehåller 20.000 iterationer och hasherns standardvärde för iterationer är 30.000, bör metoden köra password genom ytterligare 10.000 iterationer av PBKDF2.

Om din hasher inte har en arbetsfaktor, implementera metoden som en no-op (pass).

Manuell hantering av en användares lösenordLink to this heading

Modulen django.contrib.auth.hashers tillhandahåller en uppsättning funktioner för att skapa och validera hashade lösenord. Du kan använda dem oberoende av User-modellen.

check_password(password, encoded, setter=None, preferred='default')Link to this definition
acheck_password(password, encoded, asetter=None, preferred='default')Link to this definition

Asynkron version: acheck_password()

Om du vill autentisera en användare manuellt genom att jämföra ett lösenord i klartext med det hashade lösenordet i databasen kan du använda bekvämlighetsfunktionen check_password(). Den tar två obligatoriska argument: det lösenord i klartext som ska kontrolleras och det fullständiga värdet på användarens fält password i databasen som ska kontrolleras mot. Den returnerar True om de matchar, False annars. Alternativt kan du skicka en anropsbar etter som tar lösenordet och som kommer att anropas när du behöver regenerera det. Du kan också skicka preferred för att ändra en hashingalgoritm om du inte vill använda standardalgoritmen (första posten i inställningen PASSWORD_HASHERS). Se Inkluderade hasplar för namnet på algoritmen för varje hasher.

make_password(password, salt=None, hasher='default')Link to this definition

Skapar ett hashat lösenord i det format som används av denna applikation. Det tar ett obligatoriskt argument: lösenordet i klartext (sträng eller byte). Alternativt kan du ange ett salt och en hash-algoritm som ska användas om du inte vill använda standardvärdena (första posten i inställningen PASSWORD_HASHERS). Se Inkluderade hasplar för namnet på algoritmen för varje hasher. Om lösenordsargumentet är None returneras ett oanvändbart lösenord (ett lösenord som aldrig kommer att accepteras av check_password()).

is_password_usable(encoded_password)Link to this definition

Returnerar False om lösenordet är ett resultat av User.set_unusable_password().

Validering av lösenordLink to this heading

Användare väljer ofta dåliga lösenord. För att hjälpa till att mildra detta problem erbjuder Django pluggbar lösenordsvalidering. Du kan konfigurera flera lösenordsvaliderare samtidigt. Några validerare ingår i Django, men du kan också skriva dina egna.

Varje lösenordsvalidator måste tillhandahålla en hjälptext för att förklara kraven för användaren, validera ett givet lösenord och returnera ett felmeddelande om det inte uppfyller kraven, och eventuellt definiera en återuppringning för att meddelas när lösenordet för en användare har ändrats. Validerare kan också ha valfria inställningar för att finjustera deras beteende.

Valideringen styrs av inställningen AUTH_PASSWORD_VALIDATORS. Standardvärdet för inställningen är en tom lista, vilket innebär att inga validerare tillämpas. I nya projekt som skapas med standardmallen startproject är en uppsättning validerare aktiverade som standard.

Som standard används validatorer i formulären för att återställa eller ändra lösenord och i hanteringskommandona createsuperuser och changepassword. Validerare tillämpas inte på modellnivå, till exempel i User.objects.create_user() och create_superuser(), eftersom vi antar att utvecklare, inte användare, interagerar med Django på den nivån och även för att modellvalidering inte automatiskt körs som en del av att skapa modeller.

Aktivering av lösenordsvalideringLink to this heading

Lösenordsvalidering konfigureras i inställningen AUTH_PASSWORD_VALIDATORS:

Code
AUTH_PASSWORD_VALIDATORS = [
    {
        "NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator",
    },
    {
        "NAME": "django.contrib.auth.password_validation.MinimumLengthValidator",
        "OPTIONS": {
            "min_length": 9,
        },
    },
    {
        "NAME": "django.contrib.auth.password_validation.CommonPasswordValidator",
    },
    {
        "NAME": "django.contrib.auth.password_validation.NumericPasswordValidator",
    },
]

I detta exempel aktiveras alla fyra validerare som ingår:

  • UserAttributeSimilarityValidator, som kontrollerar likheten mellan lösenordet och en uppsättning attribut för användaren.

  • MinimumLengthValidator, som kontrollerar om lösenordet uppfyller en minimilängd. Den här valideraren är konfigurerad med ett anpassat alternativ: den kräver nu att den minsta längden är nio tecken, i stället för standardvärdet åtta.

  • CommonPasswordValidator, som kontrollerar om lösenordet finns med i en lista över vanliga lösenord. Som standard jämförs det med en inkluderad lista med 20 000 vanliga lösenord.

  • NumericPasswordValidator, som kontrollerar om lösenordet inte är helt numeriskt.

För UserAttributeSimilarityValidator och CommonPasswordValidator använder vi standardinställningarna i det här exemplet. NumericPasswordValidator har inga inställningar.

Hjälptexter och eventuella fel från lösenordsvalidatorer returneras alltid i den ordning de listas i AUTH_PASSWORD_VALIDATORS.

Inkluderade validerareLink to this heading

Django innehåller fyra validerare:

class MinimumLengthValidator(min_length=8)Link to this definition

Verifierar att lösenordet har en minimilängd. Minimilängden kan anpassas med parametern min_length.

get_error_message()Link to this definition

En hook för att anpassa felmeddelandet ValidationError. Standard är "Det här lösenordet är för kort. Det måste innehålla minst <min_length> tecken.".

get_help_text()Link to this definition

En hook för att anpassa validatorns hjälptext. Standard är "Ditt lösenord måste innehålla minst <min_längd> tecken.".

class UserAttributeSimilarityValidator(user_attributes=DEFAULT_USER_ATTRIBUTES, max_similarity=0.7)Link to this definition

Kontrollerar att lösenordet skiljer sig tillräckligt mycket från vissa av användarens attribut.

Parametern user_attributes bör vara en iterabel med namn på användarattribut att jämföra med. Om detta argument inte anges används standardvärdet: 'username', 'first_name', 'last_name', 'email'. Attribut som inte existerar ignoreras.

Den maximalt tillåtna likheten mellan lösenord kan ställas in på en skala från 0,1 till 1,0 med parametern max_similarity. Detta jämförs med resultatet av difflib.SequenceMatcher.quick_ratio(). Ett värde på 0,1 avvisar lösenord om de inte skiljer sig väsentligt från user_attributes, medan ett värde på 1,0 endast avvisar lösenord som är identiska med ett attributs värde.

get_error_message()Link to this definition

En hook för att anpassa felmeddelandet ValidationError. Standardvärdet är "Lösenordet är för likt <user_attribute>.".

get_help_text()Link to this definition

En hook för att anpassa validatorns hjälptext. Standard är "Ditt lösenord får inte vara för likt din övriga personliga information.".

class CommonPasswordValidator(password_list_path=DEFAULT_PASSWORD_LIST_PATH)Link to this definition

Kontrollerar att lösenordet inte är ett vanligt lösenord. Detta konverterar lösenordet till gemener (för att göra en jämförelse utan skiftlägeskänslighet) och kontrollerar det mot en lista med 20 000 vanliga lösenord som skapats av Royce Williams.

Sökvägen för password_list_path kan anges till sökvägen för en anpassad fil med vanliga lösenord. Filen ska innehålla ett lösenord med gemener per rad och kan vara i klartext eller gzippad.

get_error_message()Link to this definition

En hook för att anpassa felmeddelandet ValidationError. Standard är "Det här lösenordet är för vanligt.".

get_help_text()Link to this definition

En hook för att anpassa validatorns hjälptext. Standard är "Ditt lösenord kan inte vara ett vanligt lösenord.".

class NumericPasswordValidatorLink to this definition

Kontrollera att lösenordet inte är helt numeriskt.

get_error_message()Link to this definition

En hook för att anpassa felmeddelandet ValidationError. Standard är "Det här lösenordet är helt numeriskt.".

get_help_text()Link to this definition

En hook för att anpassa validatorns hjälptext. Standard är "Ditt lösenord kan inte vara helt numeriskt.".

Integrering av valideringLink to this heading

Det finns några funktioner i django.contrib.auth.password_validation som du kan anropa från dina egna formulär eller annan kod för att integrera lösenordsvalidering. Detta kan vara användbart om du använder anpassade formulär för lösenordsinställning, eller om du har API-anrop som gör det möjligt att ställa in lösenord, till exempel.

validate_password(password, user=None, password_validators=None)Link to this definition

Validerar ett lösenord. Om alla validerare anser att lösenordet är giltigt returneras None. Om en eller flera validerare avvisar lösenordet, skapas en ValidationError med alla felmeddelanden från validerarna.

Objektet user är valfritt: om det inte anges kan det hända att vissa validerare inte kan utföra någon validering och accepterar vilket lösenord som helst.

password_changed(password, user=None, password_validators=None)Link to this definition

Informerar alla validerare om att lösenordet har ändrats. Detta kan användas av validerare som t.ex. förhindrar återanvändning av lösenord. Detta bör anropas när lösenordet har ändrats på ett framgångsrikt sätt.

För underklasser till AbstractBaseUser kommer lösenordsfältet att markeras som ”dirty” vid anrop av set_password() som utlöser ett anrop till password_changed() efter att användaren har sparats.

password_validators_help_texts(password_validators=None)Link to this definition

Returnerar en lista med hjälptexter för alla validerare. Dessa förklarar lösenordskraven för användaren.

password_validators_help_text_html(password_validators=None)Link to this definition

Returnerar en HTML-sträng med alla hjälptexter i en <ul>. Detta är användbart när du lägger till lösenordsvalidering i formulär, eftersom du kan skicka utdata direkt till parametern help_text i ett formulärfält.

get_password_validators(validator_config)Link to this definition

Returnerar en uppsättning valideringsobjekt baserat på parametern validator_config. Som standard använder alla funktioner de validerare som definieras i AUTH_PASSWORD_VALIDATORS, men genom att anropa den här funktionen med en alternativ uppsättning validerare och sedan skicka resultatet till parametern password_validators i de andra funktionerna kommer din anpassade uppsättning validerare att användas istället. Detta är användbart när du har en typisk uppsättning validerare som kan användas för de flesta scenarier, men också har en speciell situation som kräver en anpassad uppsättning. Om du alltid använder samma uppsättning validerare behöver du inte använda den här funktionen, eftersom konfigurationen från AUTH_PASSWORD_VALIDATORS används som standard.

Strukturen för validator_config är identisk med strukturen för AUTH_PASSWORD_VALIDATORS. Returvärdet för denna funktion kan skickas till parametern password_validators i de funktioner som listas ovan.

Observera att om lösenordet skickas till någon av dessa funktioner ska det alltid vara lösenordet i klartext - inte ett hashat lösenord.

Skriva din egen validatorLink to this heading

Om Djangos inbyggda validerare inte räcker till kan du skriva dina egna lösenordsvaliderare. Validerare har ett ganska litet gränssnitt. De måste implementera två metoder:

  • validate(self, password, user=None): validerar ett lösenord. Returnerar None om lösenordet är giltigt, eller ger ett ValidationError med ett felmeddelande om lösenordet inte är giltigt. Du måste kunna hantera att user är None - om det betyder att din validerare inte kan köras, returnera None för inget fel.

  • get_help_text(): ger en hjälptext för att förklara kraven för användaren.

Alla objekt i OPTIONS i AUTH_PASSWORD_VALIDATORS för din validator kommer att skickas till konstruktören. Alla konstruktörens argument bör ha ett standardvärde.

Här är ett grundläggande exempel på en validator, med en valfri inställning:

Code
from django.core.exceptions import ValidationError
from django.utils.translation import gettext as _


class MinimumLengthValidator:
    def __init__(self, min_length=8):
        self.min_length = min_length

    def validate(self, password, user=None):
        if len(password) < self.min_length:
            raise ValidationError(
                _("This password must contain at least %(min_length)d characters."),
                code="password_too_short",
                params={"min_length": self.min_length},
            )

    def get_help_text(self):
        return _(
            "Your password must contain at least %(min_length)d characters."
            % {"min_length": self.min_length}
        )

Du kan också implementera password_changed(password, user=None), som kommer att anropas efter en lyckad lösenordsändring. Det kan till exempel användas för att förhindra återanvändning av lösenord. Men om du bestämmer dig för att lagra en användares tidigare lösenord bör du aldrig göra det i klartext.