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>

Those are the components used for storing a User’s password, separated by the dollar-sign character and consist of: the hashing algorithm, the number of algorithm iterations (work factor), the random salt, and the resulting password hash. The algorithm is one of a number of one-way hashing or password storage algorithms Django can use; see below. Iterations describe the number of times the algorithm is run over the hash. Salt is the random seed used and the hash is the result of the one-way function.

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.

However, depending on your requirements, you may choose a different algorithm, or even use a custom algorithm to match your specific security situation. Again, most users shouldn’t need to do this – if you’re not sure, you probably don’t. If you do, please read on:

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 controls the number of iterations within the hash and the size of memory for computation (N). It must be a power of 2.

  2. block_size controls the internal block size (r), tuning the algorithm to memory latency.

  3. parallelism controls how many independent computations may run in parallel (p).

  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.

We’ve chosen reasonable defaults, but you may wish to tune it up or down, depending on your security needs and available processing power and memory.

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()

If you’d like to manually authenticate a user by comparing a plaintext password to the hashed password in the database, use the convenience function check_password(). It takes two mandatory arguments: the plaintext password to check, and the full value of a user’s password field in the database to check against. It returns True if they match, False otherwise. Optionally, you can pass a callable setter that takes the password and will be called when you need to regenerate it. You can also pass preferred to change a hashing algorithm if you don’t want to use the default (first entry of PASSWORD_HASHERS setting). See Inkluderade hasplar for the algorithm name of each hasher.

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

Creates a hashed password in the format used by this application. It takes one mandatory argument: the plaintext password (string or bytes). Optionally, you can provide a salt and a hashing algorithm to use, if you don’t want to use the defaults (first entry of PASSWORD_HASHERS setting). See Inkluderade hasplar for the algorithm name of each hasher. If the password argument is None, an unusable password is returned (one that will never be accepted by 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

Validates that the password is not a common password. This converts the password to lowercase (to do a case-insensitive comparison) and checks it against a list of 20,000 common passwords created by 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.