Управление паролями в Django¶
Управление паролями - это то, что обычно не нужно изобретать без необходимости, и Django стремится предоставить безопасный и гибкий набор инструментов для управления паролями пользователей. В этом документе описывается, как Django хранит пароли, как можно настроить хэширование хранилища и некоторые утилиты для работы с хэшированными паролями.
См.также
Даже если пользователи используют надежные пароли, злоумышленники могут подслушивать их соединения. Используйте HTTPS, чтобы избежать отправки паролей (или любых других конфиденциальных данных) через обычные HTTP-соединения, поскольку они будут уязвимы для подслушивания паролей.
Как Django хранит пароли¶
Django предоставляет гибкую систему хранения паролей и по умолчанию использует PBKDF2.
Атрибут password
объекта User
представляет собой строку в данном формате:
<algorithm>$<iterations>$<salt>$<hash>
Это компоненты, используемые для хранения пароля пользователя, разделенные знаком доллара и состоящие из: алгоритма хэширования, количества итераций алгоритма (рабочий фактор), случайной соли и результирующего хэша пароля. Алгоритм является одним из нескольких алгоритмов одностороннего хэширования или хранения паролей, которые может использовать Django; см. ниже. Iterations описывает количество повторений алгоритма над хэшем. Salt - это используемое случайное зерно, а хэш - результат односторонней функции.
По умолчанию 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 в качестве алгоритма хранения по умолчанию, сделайте следующее:
Установите пакет argon2-cffi. Это можно сделать, выполнив команду
python -m pip install django[argon2]
, которая эквивалентнаpython -m pip install argon2-cffi
(вместе с любым требованием к версии изsetup.cfg
от Django).Измените
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 upgrade passwords.
Использование bcrypt
в Django¶
Bcrypt - это популярный алгоритм хранения паролей, специально разработанный для длительного хранения паролей. Он не используется Django по умолчанию, поскольку требует использования сторонних библиотек, но поскольку многие люди могут захотеть использовать его, Django поддерживает bcrypt с минимальными усилиями.
Чтобы использовать Bcrypt в качестве алгоритма хранения по умолчанию, сделайте следующее:
Установите пакет bcrypt. Это можно сделать, выполнив команду
python -m pip install django[bcrypt]
, которая эквивалентнаpython -m pip install bcrypt
(вместе с любым требованием к версии изsetup.cfg
от Django).Измените
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 upgrade passwords.
Вот и все - теперь ваша установка Django будет использовать Bcrypt в качестве алгоритма хранения по умолчанию.
Использование scrypt
с Django¶
scrypt похож на PBKDF2 и bcrypt тем, что использует заданное количество итераций для замедления атак методом перебора. Однако, поскольку PBKDF2 и bcrypt не требуют большого объема памяти, злоумышленники, обладающие достаточными ресурсами, могут проводить масштабные параллельные атаки для ускорения процесса атаки. scrypt специально разработан для использования большего объема памяти по сравнению с другими функциями извлечения ключей на основе паролей, чтобы ограничить объем параллелизма, который может использовать злоумышленник, подробнее см. в RFC 7914.
Чтобы использовать scrypt в качестве алгоритма хранения по умолчанию, сделайте следующее:
Измените
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 upgrade passwords.
Примечание
scrypt
требует OpenSSL 1.1+.
Увеличение энтропии соли¶
Большинство хэшей паролей включают соль вместе с хэшем пароля для защиты от атак на радужную таблицу. Сама соль - это случайное значение, которое увеличивает размер и, следовательно, стоимость радужной таблицы. В настоящее время она установлена на 128 бит со значением salt_entropy
в BasePasswordHasher
. По мере снижения стоимости вычислений и хранения данных это значение должно быть увеличено. При реализации собственного хешера паролей вы можете переопределить это значение, чтобы использовать желаемый уровень энтропии для ваших хешей паролей. salt_entropy
измеряется в битах.
Детали реализации
Из-за метода хранения значений соли значение salt_entropy
является минимальным значением. Например, значение 128 обеспечит соль, которая на самом деле содержит 131 бит энтропии.
Увеличение рабочего коэффициента¶
PBKDF2 и bcrypt¶
Алгоритмы PBKDF2 и bcrypt используют несколько итераций или раундов хеширования. Это намеренно замедляет злоумышленников, делая атаки на хэшированные пароли более сложными. Однако по мере роста вычислительной мощности количество итераций необходимо увеличивать. Мы выбрали разумное значение по умолчанию (и будем увеличивать его с каждым выпуском Django), но вы можете изменить его в большую или меньшую сторону, в зависимости от ваших потребностей в безопасности и доступной вычислительной мощности. Для этого вы создадите подкласс соответствующего алгоритма и переопределите параметр iterations
(используйте параметр rounds
при создании подкласса хэшера bcrypt). Например, чтобы увеличить количество итераций, используемых алгоритмом PBKDF2 по умолчанию:
``django.contrib.auth.hashers.PBKDF2PasswordHasher``Cr
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
.Добавьте ваш новый хэшер в качестве первой записи в
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
итераций.
Аргон2¶
Argon2 имеет следующие атрибуты, которые могут быть настроены:
time_cost
управляет количеством итераций внутри хэша.memory_cost
контролирует размер памяти, которая должна быть использована при вычислении хэша.parallelism
контролирует, на скольких процессорах можно распараллелить вычисление хэша.
Вероятно, значения этих атрибутов по умолчанию вас вполне устроят. Если вы определите, что хэш пароля работает слишком быстро или слишком медленно, вы можете настроить его следующим образом:
- Выберите
parallelism
в качестве количества потоков, которые вы можете выделить для вычисления хэша. - Выберите
memory_cost
как КиБ памяти, которую вы можете выделить. - Настройте
time_cost
и измерьте время, затрачиваемое на хэширование пароля. Выберите значениеtime_cost
, которое занимает приемлемое для вас время. Если значениеtime_cost
, установленное на 1, неприемлемо медленно, уменьшите значениеmemory_cost
.
memory_cost
интерпретация
Утилита командной строки argon2 и некоторые другие библиотеки интерпретируют параметр memory_cost
иначе, чем значение, которое использует Django. Для преобразования используется memory_cost == 2 ** memory_cost_commandline
.
scrypt
¶
scrypt имеет следующие атрибуты, которые могут быть настроены:
work_factor
управляет количеством итераций внутри хэша.block_size
parallelism
управляет тем, сколько потоков будет работать параллельно.maxmem
ограничивает максимальный размер памяти, который может быть использован при вычислении хэша. По умолчанию установлено значение0
, что означает ограничение по умолчанию из библиотеки OpenSSL.
Мы выбрали разумные значения по умолчанию, но вы можете изменить их в большую или меньшую сторону, в зависимости от ваших потребностей в безопасности и доступной вычислительной мощности.
Оценка использования памяти
Минимальные требования к памяти для scrypt составляют:
work_factor * 2 * block_size * 64
поэтому может потребоваться подстройка maxmem
при изменении значений work_factor
или block_size
.
Обновление пароля¶
При входе пользователей в систему, если их пароли хранятся не в предпочтительном алгоритме, Django автоматически обновит алгоритм до предпочтительного. Это означает, что старые версии Django будут автоматически становиться более безопасными при входе пользователей, а также то, что вы сможете переходить на новые (и лучшие) алгоритмы хранения по мере их изобретения.
Однако Django может обновлять только те пароли, которые используют алгоритмы, упомянутые в PASSWORD_HASHERS
, поэтому при переходе на новые системы вы должны следить за тем, чтобы никогда не удалять записи из этого списка. Если вы это сделаете, пользователи, использующие неупомянутые алгоритмы, не смогут обновиться. Хешированные пароли будут обновляться при увеличении (или уменьшении) количества итераций PBKDF2, раундов bcrypt или атрибутов argon2.
Имейте в виду, что если все пароли в вашей базе данных не закодированы в алгоритме хешера по умолчанию, вы можете быть уязвимы для временной атаки перечисления пользователей из-за разницы между длительностью запроса на вход для пользователя с паролем, закодированным в алгоритме не по умолчанию, и длительностью запроса на вход для несуществующего пользователя (который использует хешер по умолчанию). Вы можете смягчить эту проблему, используя upgrading older password hashes.
Обновление пароля без необходимости входа в систему¶
Если у вас есть база данных с устаревшим и слабым хэшем, например MD5, вы можете захотеть обновить его самостоятельно, а не ждать, пока обновление произойдет при входе пользователя в систему (что может никогда не произойти, если пользователь не вернется на ваш сайт). В этом случае можно использовать «обернутый» хешер паролей.
В данном примере мы переведем коллекцию MD5-хэшей на использование PBKDF2(MD5(password)) и добавим соответствующий хэш для проверки правильности ввода пароля пользователем при входе в систему. Мы предполагаем, что используем встроенную модель User
и что в нашем проекте есть приложение accounts
. Вы можете модифицировать паттерн для работы с любым алгоритмом или с пользовательской моделью.
Сначала мы добавим пользовательский хэшер:
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)
Миграция данных может выглядеть примерно так:
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
:
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')[исходный код]¶ Если вы хотите вручную проверить подлинность пользователя, сравнив его пароль с хэшированным паролем в базе данных, воспользуйтесь удобной функцией
check_password()
. Она принимает два обязательных аргумента: пароль для проверки и полное значение поляpassword
пользователя в базе данных. В случае совпадения возвращаетсяTrue
, в противном случаеFalse
. В качестве опции можно передать вызываемую переменнуюsetter
, которая принимает пароль и будет вызываться, когда потребуется его регенерация. Также можно передатьpreferred
для изменения алгоритма хеширования, если вы не хотите использовать алгоритм по умолчанию (первый элемент настройкиPASSWORD_HASHERS
). Имя алгоритма для каждого хешера см. в Входящие в комплект шайбы.
-
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 отклоняет только те пароли, которые идентичны значению атрибута.Changed in Django 2.2.26:Параметр
max_similarity
был ограничен минимальным значением 0,1.
-
class
CommonPasswordValidator
(password_list_path=DEFAULT_PASSWORD_LIST_PATH)[исходный код]¶ Проверяет, что пароль не является обычным паролем. При этом пароль преобразуется в нижний регистр (для сравнения без учета регистра) и сверяется со списком из 20 000 распространенных паролей, созданным программой Royce Williams.
Параметр
password_list_path
может быть установлен на путь к пользовательскому файлу общих паролей. Этот файл должен содержать один пароль в нижнем регистре на строку и может быть обычным текстом или gzipped.Changed in 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
), которая будет вызываться после успешной смены пароля. Это можно использовать, например, для предотвращения повторного использования пароля. Однако, если вы решили хранить предыдущие пароли пользователя, никогда не делайте это открытым текстом.