Spec-Zone.ru › Django 5.0

Управление паролями в Django

Управление паролями — это то, что обычно не стоит изобретать заново, и Django стремится предоставить безопасный и гибкий набор инструментов для управления паролями пользователей. Этот документ описывает, как Django хранит пароли, как можно настроить хэширование хранения и некоторые утилиты для работы с хэшированными паролями.

См. также

Даже если пользователи используют сильные пароли, злоумышленники могут перехватывать их соединения. Используйте HTTPS, чтобы не отправлять пароли (или любые другие конфиденциальные данные) по обычным HTTP-соединениям, так как они будут уязвимы к перехвату паролей.

Как Django хранит пароли

Django предоставляет гибкую систему хранения паролей и по умолчанию использует PBKDF2.

Атрибут password объекта User — это строка в таком формате:

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

Это компоненты, используемые для хранения пароля пользователя, разделенные символом «доллар» и состоящие из: алгоритма хэширования, количества итераций алгоритма (фактор сложности), случайной соли и результирующего хэша пароля. Алгоритм — это один из ряда односторонних алгоритмов хэширования или хранения паролей, которые может использовать Django; см. ниже. Итерации описывают количество раз, когда алгоритм выполняется над хэшем. Соль — это случайное начальное значение, а хэш — результат односторонней функции.

По умолчанию Django использует алгоритм PBKDF2 с хэшем SHA256, механизм расширения паролей, рекомендуемый NIST. Этого должно быть достаточно для большинства пользователей: он достаточно безопасен, для взлома которого требуются огромные вычислительные мощности.

Однако в зависимости от ваших требований вы можете выбрать другой алгоритм или даже использовать пользовательский алгоритм, чтобы соответствовать вашей конкретной ситуации с безопасностью. Опять же, большинству пользователей этого делать не нужно — если вы не уверены, вам, вероятно, не нужно. Если вы это сделаете, пожалуйста, читайте дальше:

Django выбирает используемый алгоритм, обращаясь к настройке PASSWORD_HASHERS. Это список классов алгоритмов хэширования, которые поддерживает эта установка Django.

Для хранения паролей Django будет использовать первый хэшер в PASSWORD_HASHERS. Для хранения новых паролей с другим алгоритмом поместите предпочтительный алгоритм первым в PASSWORD_HASHERS.

Для проверки паролей Django найдёт хэшер в списке, который соответствует имени алгоритма в сохранённом пароле. Если сохранённый пароль называет алгоритм, которого нет в PASSWORD_HASHERS, попытка его проверки вызовет ValueError.

Значение по умолчанию для PASSWORD_HASHERS:

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",
]

Это означает, что Django будет использовать PBKDF2 для хранения всех паролей, но будет поддерживать проверку паролей, сохранённых с PBKDF2SHA1, argon2 и bcrypt.

В следующих разделах описываются несколько распространённых способов, которыми продвинутые пользователи могут изменить эту настройку.

Использование Argon2 с Django

Argon2 — победитель конкурса 2015 года Password Hashing Competition, организованного сообществом открытого конкурса для выбора алгоритма хэширования следующего поколения. Он разработан так, чтобы быть не легче для вычисления на специализированном оборудовании, чем на обычном процессоре. По умолчанию вариантом хэшера паролей Argon2 является Argon2id.

Argon2 не является значением по умолчанию для Django, так как требует библиотеки сторонних разработчиков. Однако эксперты конкурса по хэшированию паролей рекомендуют немедленное использование Argon2 вместо других поддерживаемых Django алгоритмов.

Чтобы использовать Argon2id в качестве алгоритма хранения по умолчанию, выполните следующие действия:

  1. Установите пакет argon2-cffi. Это можно сделать, выполнив python -m pip install django[argon2], что эквивалентно python -m pip install argon2-cffi (вместе с любыми требованиями к версии из setup.cfg).
  2. Измените PASSWORD_HASHERS, чтобы список Argon2PasswordHasher стоял первым. То есть в вашем файле настроек вы бы указали:

    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",
    ]
    

    Сохраните и/или добавьте любые записи в этом списке, если вам нужно, чтобы Django обновлял пароли.

Использование bcrypt с Django

Bcrypt — популярный алгоритм хранения паролей, специально разработанный для долгосрочного хранения паролей. Это не значение по умолчанию, используемое Django, так как требует использования библиотек сторонних разработчиков, но, поскольку многие люди могут захотеть использовать его, Django поддерживает bcrypt с минимальными усилиями.

Чтобы использовать Bcrypt в качестве алгоритма хранения по умолчанию, выполните следующие действия:

  1. Установите пакет bcrypt. Это можно сделать, выполнив python -m pip install django[bcrypt], что эквивалентно python -m pip install bcrypt (вместе с любыми требованиями к версии из setup.cfg).
  2. Измените PASSWORD_HASHERS, чтобы список BCryptSHA256PasswordHasher стоял первым. То есть в вашем файле настроек вы бы указали:

    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",
    ]
    

    Сохраните и/или добавьте любые записи в этом списке, если вам нужно, чтобы Django обновлял пароли.

Вот и всё — теперь ваша установка Django будет использовать Bcrypt в качестве алгоритма хранения по умолчанию.

Использование scrypt с Django

scrypt похож на PBKDF2 и bcrypt в использовании набора итераций для замедления атак методом перебора. Однако, поскольку PBKDF2 и bcrypt не требуют большого объёма памяти, злоумышленники с достаточными ресурсами могут запускать масштабные параллельные атаки, чтобы ускорить процесс атаки. scrypt специально разработан для использования большего объёма памяти по сравнению с другими функциями вывода ключей на основе паролей, чтобы ограничить количество параллелизма, которое может использовать злоумышленник, см. RFC 7914 для получения более подробной информации.

Чтобы использовать scrypt в качестве алгоритма хранения по умолчанию, выполните следующие действия:

  1. Измените PASSWORD_HASHERS, чтобы список ScryptPasswordHasher стоял первым. То есть в вашем файле настроек:

    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",
    ]
    

    Сохраните и/или добавьте любые записи в этом списке, если вам нужно, чтобы Django обновлял пароли.

Примечание

scrypt требует OpenSSL 1.1+.

Увеличение энтропии соли

Большинство хэшей паролей включают соль вместе с хэшем пароля, чтобы защититься от атак с использованием радужных таблиц. Сама соль — это случайное значение, которое увеличивает размер и, следовательно, стоимость радужной таблицы и в настоящее время установлена на 128 бит с помощью значения salt_entropy в BasePasswordHasher. По мере снижения вычислительных и хранилищных затрат это значение следует повысить. При реализации собственного хэшера паролей вы можете переопределить это значение, чтобы использовать желаемый уровень энтропии для хэшей паролей. salt_entropy измеряется в битах.

Деталь реализации

Из-за метода хранения значений соли значение salt_entropy фактически является минимальным значением. Например, значение 128 обеспечит соль, которая фактически будет содержать 131 бит энтропии.

Увеличение фактора сложности алгоритма паролей

PBKDF2 и bcrypt

Алгоритмы PBKDF2 и bcrypt используют определенное количество итераций или раундов хэширования. Это преднамеренно замедляет злоумышленников, что затрудняет атаки на хэшированные пароли. Однако по мере увеличения вычислительной мощности количество итераций необходимо увеличивать. Мы выбрали разумное значение по умолчанию (и будем увеличивать его с каждым выпуском Django), но вы можете настроить его вверх или вниз в зависимости от ваших потребностей в безопасности и доступной вычислительной мощности. Для этого вы создадите подкласс соответствующего алгоритма и переопределите параметр iterations (используйте параметр rounds при создании подкласса хэшера bcrypt). Например, чтобы увеличить количество итераций, используемых алгоритмом PBKDF2 по умолчанию:

  1. Создайте подкласс django.contrib.auth.hashers.PBKDF2PasswordHasher

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

    Сохраните это где-нибудь в вашем проекте. Например, вы можете поместить это в файл, такой как myproject/hashers.py.

  2. Добавьте свой новый хэшер в качестве первой записи в PASSWORD_HASHERS:

    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",
    ]
    

Вот и всё — теперь ваша установка Django будет использовать больше итераций при хранении паролей с помощью PBKDF2.

Примечание

bcrypt rounds — это логарифмический фактор сложности, например, 12 раундов означают 2 ** 12 итераций.

Argon2

Алгоритм Argon2 имеет следующие атрибуты, которые можно настроить:

  1. time_cost управляет количеством итераций в хэше.
  2. memory_cost управляет размером памяти, которая должна использоваться во время вычисления хэша.
  3. parallelism управляет количеством ЦП, на которых вычисление хэша может быть распараллелено.

Значения этих атрибутов по умолчанию, вероятно, подойдут вам. Если вы определите, что хэш пароля слишком быстрый или слишком медленный, вы можете настроить его следующим образом:

  1. Выберите parallelism в качестве количества потоков, которые вы можете использовать для вычисления хэша.
  2. Выберите memory_cost в качестве объема памяти (в КБ), которую вы можете выделить.
  3. Настройте time_cost и измерьте время, необходимое для хэширования пароля. Выберите значение time_cost, которое занимает приемлемое время для вас. Если time_cost со значением 1 неприемлемо медленно, уменьшите memory_cost.

memory_cost интерпретация

Утилита argon2 командной строки и некоторые другие библиотеки интерпретируют параметр memory_cost по-другому, чем Django. Преобразование задаётся формулой memory_cost == 2 ** memory_cost_commandline.

scrypt

scrypt имеет следующие атрибуты, которые можно настроить:

  1. work_factor управляет количеством итераций в хэше.
  2. block_size
  3. parallelism управляет количеством потоков, которые будут работать параллельно.
  4. maxmem ограничивает максимальный размер памяти, который может быть использован во время вычисления хэша. По умолчанию 0, что означает ограничение по умолчанию из библиотеки OpenSSL.

Мы выбрали разумные значения по умолчанию, но вы можете настроить их вверх или вниз, в зависимости от ваших потребностей в безопасности и доступной вычислительной мощности.

Оценка использования памяти

Минимальные требования к памяти для scrypt составляют:

work_factor * 2 * block_size * 64

поэтому вам может потребоваться настроить maxmem при изменении значений work_factor или block_size.

Обновление паролей

При входе пользователей, если их пароли хранятся с алгоритмом, отличным от предпочтительного, Django автоматически обновит алгоритм до предпочтительного. Это означает, что старые установки Django будут автоматически становиться более безопасными по мере входа пользователей, а также означает, что вы можете перейти к новым (и лучшим) алгоритмам хранения по мере их появления.

Однако Django может обновлять только пароли, использующие алгоритмы, упомянутые в PASSWORD_HASHERS, поэтому при обновлении до новых систем вы должны убедиться, что никогда не удаляете записи из этого списка. В противном случае пользователи, использующие неуказанные алгоритмы, не смогут обновить свои пароли. Хэшированные пароли будут обновлены при увеличении (или уменьшении) количества итераций PBKDF2, раундов bcrypt или атрибутов argon2.

Помните, что если все пароли в вашей базе данных не закодированы по умолчанию алгоритмом хэширования, вы можете быть уязвимы к атаке с перечислением пользователей по времени из-за различия во времени запроса входа пользователя с паролем, закодированным в алгоритме, отличном от стандартного, и времени запроса входа несуществующего пользователя (который использует стандартный алгоритм хэширования). Вы можете смягчить это, обновив старые хэши паролей.

Обновление паролей без требования входа

Если у вас есть существующая база данных со старым, слабым хэшем, таким как MD5, вы можете сами обновить эти хэши вместо того, чтобы ждать обновления при входе пользователя (что может никогда не произойти, если пользователь не вернется на ваш сайт). В этом случае вы можете использовать «обернутый» хэшер паролей.

В этом примере мы переведём коллекцию хэшей MD5 на использование PBKDF2(MD5(пароль)) и добавим соответствующий хэшер паролей для проверки правильности введённого пользователем пароля при входе. Мы предполагаем, что мы используем встроенную модель User и что наш проект имеет приложение accounts. Вы можете изменить шаблон, чтобы он работал с любым алгоритмом или с настраиваемой моделью пользователя.

Сначала мы добавим настраиваемый хэшер:

accounts/hashers.py
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)

Миграция данных может выглядеть примерно так:

accounts/migrations/0002_migrate_md5_passwords.py
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),
    ]

Помните, что эта миграция может занять несколько минут для нескольких тысяч пользователей, в зависимости от скорости вашего оборудования.

Наконец, мы добавим параметр PASSWORD_HASHERS:

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

В этот список включите все другие хэши, используемые вашим сайтом.

Включённые хэши

Полный список хэширователей, включённых в Django, следующий:

[
    "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",
]

Соответствующие имена алгоритмов:

  • pbkdf2_sha256
  • pbkdf2_sha1
  • argon2
  • bcrypt_sha256
  • bcrypt
  • scrypt
  • md5

Написание собственного хэшера паролей

Если вы пишете собственный хэшер паролей, содержащий коэффициент сложности, например, число итераций, вам следует реализовать метод harden_runtime(self, password, encoded), чтобы преодолеть разрыв во времени выполнения между коэффициентом сложности, указанным в хэше encoded пароля, и коэффициентом сложности по умолчанию хэшера. Это предотвращает атаку с перечислением пользователей по времени из-за различий во времени запроса входа пользователя с паролем, закодированным в старом количестве итераций, и времени запроса входа несуществующего пользователя (который использует количество итераций по умолчанию хэшера).

Принимая PBKDF2 как пример, если encoded содержит 20 000 итераций, а значение по умолчанию iterations хэшера — 30 000, метод должен выполнить password через ещё 10 000 итераций PBKDF2.

Если ваш хэшер не имеет коэффициента сложности, реализуйте этот метод как no-op (pass).

Ручное управление паролем пользователя

Модуль django.contrib.auth.hashers предоставляет набор функций для создания и проверки хэшированных паролей. Вы можете использовать их независимо от модели User.

check_password(password, encoded, setter=None, preferred='default')
acheck_password(password, encoded, asetter=None, preferred='default')

Асинхронная версия: acheck_password()

Если вы хотите вручную аутентифицировать пользователя, сравнивая обычный пароль с хэшированным паролем в базе данных, используйте удобную функцию check_password(). Она принимает два обязательных аргумента: обычный текст пароля для проверки и полное значение поля password пользователя в базе данных для проверки. Она возвращает True, если они совпадают, и False, в противном случае. Дополнительно вы можете передать вызываемую функцию setter, которая принимает пароль и будет вызываться при необходимости его перегенерации. Вы также можете передать preferred, чтобы изменить алгоритм хэширования, если вы не хотите использовать стандартный (первый элемент в настройке PASSWORD_HASHERS). См. Включённые хэши для имени алгоритма каждого хэшера.

Изменено в Django 5.0:

acheck_password() метод был добавлен.

make_password(password, salt=None, hasher='default')

Создаёт хэшированный пароль в формате, используемом этим приложением. Она принимает один обязательный аргумент: пароль в текстовом формате (строка или байты). Дополнительно вы можете указать соль и алгоритм хэширования, если вы не хотите использовать значения по умолчанию (первый элемент в настройке PASSWORD_HASHERS). См. Включённые хэши для имени алгоритма каждого хэшера. Если аргумент password — None, возвращается непригодный пароль (который никогда не будет принят check_password()).

is_password_usable(encoded_password)

Возвращает False если пароль является результатом User.set_unusable_password().

Проверка паролей

Пользователи часто выбирают слабые пароли. Чтобы смягчить эту проблему, Django предлагает настраиваемую проверку паролей. Вы можете одновременно настроить несколько валидаторов паролей. В Django включено несколько валидаторов, но вы также можете написать свои собственные.

Каждый валидатор паролей должен предоставить текст справки для объяснения требований пользователю, проверить заданный пароль и вернуть сообщение об ошибке, если он не соответствует требованиям, а также (необязательно) определить обратный вызов, чтобы быть уведомлённым, когда пароль пользователя был изменён. У валидаторов также могут быть необязательные настройки для тонкой настройки их поведения.

Валидация контролируется параметром AUTH_PASSWORD_VALIDATORS. По умолчанию этот параметр содержит пустой список, что означает, что валидаторы не применяются. В новых проектах, созданных с помощью шаблона по умолчанию startproject, набор валидаторов включён по умолчанию.

По умолчанию, валидаторы используются в формах для сброса или изменения паролей, а также в командных утилитах createsuperuser и changepassword. Валидаторы не применяются на уровне модели, например, в User.objects.create_user() и create_superuser(), так как мы предполагаем, что разработчики, а не пользователи, взаимодействуют с Django на этом уровне, а также потому, что валидация модели не запускается автоматически в рамках создания моделей.

Примечание

Валидация паролей может предотвратить использование многих типов слабых паролей. Однако тот факт, что пароль прошёл все валидаторы, не гарантирует, что он является надёжным. Существует множество факторов, которые могут ослабить пароль, которые не обнаруживаются даже самыми продвинутыми валидаторами паролей.

Включение валидации паролей

Валидация паролей настраивается в параметре AUTH_PASSWORD_VALIDATORS:

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",
    },
]

В этом примере все четыре включённых валидатора включены:

  • UserAttributeSimilarityValidator, который проверяет сходство пароля с набором атрибутов пользователя.
  • MinimumLengthValidator, который проверяет, соответствует ли пароль минимальной длине. Этот валидатор настроен с пользовательским параметром: теперь он требует, чтобы минимальная длина составляла девять символов, вместо стандартных восьми.
  • CommonPasswordValidator, который проверяет, присутствует ли пароль в списке общих паролей. По умолчанию он сравнивает с включённым списком из 20 000 общих паролей.
  • NumericPasswordValidator, который проверяет, что пароль не состоит целиком из цифр.

Для UserAttributeSimilarityValidator и CommonPasswordValidator в этом примере используются настройки по умолчанию. NumericPasswordValidator не имеет настроек.

Тексты справки и любые ошибки от валидаторов паролей всегда возвращаются в порядке их перечисления в AUTH_PASSWORD_VALIDATORS.

Включенные валидаторы

Django включает четыре валидатора:

class MinimumLengthValidator(min_length=8)

Проверяет, что длина пароля не меньше минимальной. Минимальную длину можно настроить с помощью параметра min_length.

class UserAttributeSimilarityValidator(user_attributes=DEFAULT_USER_ATTRIBUTES, max_similarity=0.7)

Проверяет, что пароль достаточно отличается от определённых атрибутов пользователя.

Параметр user_attributes должен быть итерируемым объектом имён атрибутов пользователя, с которыми нужно сравнить пароль. Если этот аргумент не предоставлен, используется значение по умолчанию: 'username', 'first_name', 'last_name', 'email'. Атрибуты, которые не существуют, игнорируются.

Максимально допустимое сходство паролей может быть установлено в диапазоне от 0,1 до 1,0 с помощью параметра max_similarity. Это сравнивается с результатом difflib.SequenceMatcher.quick_ratio(). Значение 0,1 отклоняет пароли, если они существенно отличаются от user_attributes, в то время как значение 1,0 отклоняет только пароли, которые идентичны значению атрибута.

Изменено в Django 2.2.26:

Параметр max_similarity был ограничен минимальным значением 0,1.

class CommonPasswordValidator(password_list_path=DEFAULT_PASSWORD_LIST_PATH)

Проверяет, что пароль не является распространённым. Преобразует пароль в нижний регистр (для выполнения сравнения без учёта регистра) и проверяет его в списке из 20 000 общих паролей, созданных Royce Williams в https://gist.github.com/roycewilliams/226886fd01572964e1431ac8afc999ce.

Параметр password_list_path может быть установлен на путь к файлу с пользовательскими общими паролями. Этот файл должен содержать по одному паролю в нижнем регистре в каждой строке и может быть текстовым или сжатым в формате gzip.

Изменено в Django 4.2:

Список из 20 000 общих паролей был обновлён до последней версии.

class NumericPasswordValidator

Проверяет, что пароль не состоит целиком из цифр.

Интеграция валидации

В django.contrib.auth.password_validation есть несколько функций, которые вы можете вызвать из собственных форм или другого кода для интеграции валидации паролей. Это может быть полезно, если вы используете пользовательские формы для установки паролей или имеете API-вызовы, позволяющие устанавливать пароли, например.

validate_password(password, user=None, password_validators=None)

Валидирует пароль. Если все валидаторы считают пароль валидным, возвращает None. Если один или несколько валидаторов отклоняют пароль, возникает исключение ValidationError со всеми сообщениями об ошибках от валидаторов.

Объект user является необязательным: если он не предоставлен, некоторые валидаторы могут не иметь возможности выполнить валидацию и примут любой пароль.

password_changed(password, user=None, password_validators=None)

Сообщает всем валидаторам, что пароль был изменён. Это можно использовать для валидаторов, которые предотвращают повторное использование паролей. Вызвать эту функцию нужно после успешного изменения пароля.

Для подклассов AbstractBaseUser, поле пароля будет помечено как «изменённое» при вызове set_password(), что инициирует вызов password_changed() после сохранения пользователя.

password_validators_help_texts(password_validators=None)

Возвращает список текстов справки всех валидаторов. Они объясняют требования к паролю пользователю.

password_validators_help_text_html(password_validators=None)

Возвращает строку HTML со всеми текстами справки в <ul>. Это полезно при добавлении валидации паролей в формы, так как вы можете передать результат непосредственно в параметр help_text поля формы.

get_password_validators(validator_config)

Возвращает набор объектов валидаторов, основанных на параметре validator_config. По умолчанию все функции используют валидаторы, определённые в AUTH_PASSWORD_VALIDATORS, но вызывая эту функцию с альтернативным набором валидаторов и передавая результат в параметр password_validators других функций, вместо этого будут использоваться ваши пользовательские валидаторы. Это полезно, когда у вас есть типичный набор валидаторов для большинства сценариев, но также есть особый случай, который требует пользовательского набора. Если вы всегда используете один и тот же набор валидаторов, нет необходимости использовать эту функцию, так как по умолчанию используется конфигурация из AUTH_PASSWORD_VALIDATORS.

Структура validator_config идентична структуре AUTH_PASSWORD_VALIDATORS. Возвращаемое значение этой функции может быть передано в параметр password_validators функций, перечисленных выше.

Обратите внимание, что при передаче пароля одной из этих функций, это всегда должен быть явный текст пароля — не хэшированный.

Написание собственного валидатора

Если встроенных валидаторов Django недостаточно, вы можете написать свои собственные валидаторы паролей. У валидаторов довольно ограниченный интерфейс. Они должны реализовать два метода:

  • validate(self, password, user=None): валидирует пароль. Возвращает None если пароль валидный, или вызывает ValidationError с сообщением об ошибке, если пароль не валиден. Вы должны уметь обрабатывать случай, когда user является None, — если это означает, что ваш валидатор не может работать, возвращайте None для отсутствия ошибки.
  • get_help_text(): предоставляет текст справки для объяснения требований пользователю.

Любые элементы в OPTIONS в AUTH_PASSWORD_VALIDATORS для вашего валидатора будут переданы в конструктор. Все аргументы конструктора должны иметь значение по умолчанию.

Вот базовый пример валидатора с одним необязательным параметром:

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

Вы также можете реализовать password_changed(password, user=None, который будет вызван после успешного изменения пароля. Это можно использовать, например, для предотвращения повторного использования пароля. Однако, если вы решите хранить предыдущие пароли пользователя, никогда не делайте этого в явном виде.

© Django Software Foundation and individual contributors
Licensed under the BSD License.
https://docs.djangoproject.com/en/5.0/topics/auth/passwords/

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API