Управление паролями в Django
Управление паролями — это то, что, как правило, не следует изобретать заново, и Django стремится предоставить набор безопасных и гибких инструментов для управления паролями пользователей. В данном документе описано, как Django хранит пароли, как можно настроить хэширование хранения и некоторые утилиты для работы с хэшированными паролями.
См. также
Даже если пользователи используют надежные пароли, злоумышленники могут перехватывать их соединения. Используйте HTTPS, чтобы избежать отправки паролей (или любых других конфиденциальных данных) по незащищенным соединениям HTTP, так как они будут уязвимы к перехвату паролей.
Как Django хранит пароли
Django предоставляет гибкую систему хранения паролей и по умолчанию использует PBKDF2.
Атрибут password объекта User — это строка в следующем формате:
<algorithm>$<iterations>$<salt>$<hash>
Это компоненты, используемые для хранения пароля пользователя, разделенные символом «доллар»: алгоритм хэширования, количество итераций алгоритма (фактор сложности), случайная соль и полученный хэш пароля. Алгоритм — это один из множества односторонних алгоритмов хэширования или хранения паролей, которые может использовать Django; см. ниже. Итерации описывают количество раз, когда алгоритм выполняется над хэшем. Соль — это случайное начальное значение, а хэш — результат односторонней функции.
По умолчанию Django использует алгоритм PBKDF2 с хэшем SHA256, механизм расширения пароля, рекомендованный NIST. Этого должно быть достаточно для большинства пользователей: это достаточно безопасно, и для взлома требуется значительное количество вычислительных ресурсов.
Однако, в зависимости от ваших потребностей, вы можете выбрать другой алгоритм или даже использовать пользовательский алгоритм, чтобы соответствовать вашей конкретной ситуации безопасности. Опять же, большинству пользователей это не нужно — если вы не уверены, вам, вероятно, не нужно. Если вы хотите, прочитайте дальше:
Django выбирает используемый алгоритм, обращаясь к настройке PASSWORD_HASHERS. Это список классов алгоритмов хэширования, которые поддерживает данная установка Django. Первая запись в этом списке (то есть settings.PASSWORD_HASHERS[0]) будет использоваться для хранения паролей, а все другие записи — это валидные хэшировщики, которые могут использоваться для проверки существующих паролей. Это означает, что если вы хотите использовать другой алгоритм, вам нужно изменить PASSWORD_HASHERS, чтобы поместить предпочитаемый алгоритм в начале списка.
Значение по умолчанию для 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.BCryptPasswordHasher',
]
Это означает, что Django будет использовать PBKDF2 для хранения всех паролей, но будет поддерживать проверку паролей, хранящихся с PBKDF2SHA1, argon2 и bcrypt.
В следующих разделах описано несколько распространенных способов, которыми продвинутые пользователи могут изменить эту настройку.
Использование Argon2 с Django
Argon2 — победитель конкурса Password Hashing Competition 2015 года, организованного сообществом открытого конкурса по выбору алгоритма хэширования следующего поколения. Он разработан таким образом, чтобы его выполнение на специализированном оборудовании не было проще, чем на обычном процессоре.
Argon2 не является по умолчанию для Django, потому что он требует сторонней библиотеки. Однако панель конкурса по хэшированию паролей рекомендует немедленное использование Argon2 вместо других алгоритмов, поддерживаемых Django.
Чтобы использовать Argon2 в качестве алгоритма хранения по умолчанию, выполните следующие действия:
- Установите библиотеку argon2-cffi. Это можно сделать, выполнив
pip install django[argon2], что эквивалентноpip install argon2-cffi, (вместе с любым требованием версии изsetup.py). -
Измените
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.BCryptPasswordHasher', ]Сохраните и/или добавьте любые записи в этот список, если вам нужно, чтобы Django обновил пароли.
Использование bcrypt с Django
Bcrypt — популярный алгоритм хранения паролей, специально разработанный для долгосрочного хранения паролей. Он не используется по умолчанию в Django, так как требует использования сторонних библиотек, но поскольку многие пользователи могут его использовать, Django поддерживает bcrypt с минимальными усилиями.
Чтобы использовать Bcrypt в качестве алгоритма хранения по умолчанию, выполните следующие действия:
- Установите библиотеку bcrypt. Это можно сделать, выполнив
pip install django[bcrypt], что эквивалентноpip install bcrypt(вместе с любым требованием версии изsetup.py). -
Измените
PASSWORD_HASHERS, чтобы поместитьBCryptSHA256PasswordHasherв начало. То есть в вашем файле настроек вы бы добавили:PASSWORD_HASHERS = [ 'django.contrib.auth.hashers.BCryptSHA256PasswordHasher', 'django.contrib.auth.hashers.BCryptPasswordHasher', 'django.contrib.auth.hashers.PBKDF2PasswordHasher', 'django.contrib.auth.hashers.PBKDF2SHA1PasswordHasher', 'django.contrib.auth.hashers.Argon2PasswordHasher', ]Сохраните и/или добавьте любые записи в этот список, если вам нужно, чтобы Django обновил пароли.
Вот и все — теперь ваша установка Django будет использовать Bcrypt в качестве алгоритма хранения по умолчанию.
Обрезка паролей с BCryptPasswordHasher
Разработчики bcrypt обрезают все пароли на 72 символа, что означает, что bcrypt(password_with_100_chars) == bcrypt(password_with_100_chars[:72]). Исходный BCryptPasswordHasher не имеет специальной обработки и, следовательно, также подвержен этому скрытому ограничению длины пароля. BCryptSHA256PasswordHasher исправляет это, сначала хэшируя пароль с использованием sha256. Это предотвращает обрезку пароля, поэтому следует предпочесть BCryptPasswordHasher. Практические последствия этой обрезки довольно незначительны, поскольку средний пользователь не имеет пароля длиной более 72 символов, и даже при обрезке до 72 символов вычислительные мощности, необходимые для взлома bcrypt за разумное время, остаются астрономическими. Тем не менее, мы рекомендуем использовать BCryptSHA256PasswordHasher по принципу «лучше перестраховаться».
Другие реализации bcrypt
Существуют несколько других реализаций, которые позволяют использовать bcrypt с Django. Поддержка bcrypt в Django НЕ совместима напрямую с ними. Для обновления вам необходимо изменить хэши в вашей базе данных, чтобы они имели вид bcrypt$(raw bcrypt
output). Например: bcrypt$$2a$12$NT0I31Sa7ihGEWpka9ASYrEFkhuTNeBQ2xfZskIiiJeyFXhRgS.Sy.
Увеличение фактора сложности алгоритма паролей
PBKDF2 и bcrypt
Алгоритмы PBKDF2 и bcrypt используют определенное количество итераций или раундов хэширования. Это намеренно замедляет злоумышленников, что затрудняет атаки на хэшированные пароли. Однако по мере увеличения вычислительной мощности необходимо увеличивать количество итераций. Мы выбрали разумное значение по умолчанию (и будем увеличивать его с каждым выпуском Django), но вы можете настроить его вверх или вниз в зависимости от ваших потребностей в безопасности и доступной вычислительной мощности. Для этого вы создадите подкласс соответствующего алгоритма и переопределите параметры iterations. Например, чтобы увеличить количество итераций, используемых алгоритмом PBKDF2 по умолчанию:
-
Создайте подкласс
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. -
Добавьте ваш новый хэшировщик как первую запись в
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.BCryptPasswordHasher', ]
Вот и все — теперь ваша установка Django будет использовать больше итераций при хранении паролей с помощью PBKDF2.
Argon2
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.
Обновление паролей
При входе пользователей, если их пароли хранятся с использованием любого алгоритма, отличного от предпочитаемого, Django автоматически обновит алгоритм до предпочитаемого. Это означает, что старые установки Django будут автоматически становиться более безопасными по мере входа пользователей, а также означает, что вы можете перейти к новым (и лучшим) алгоритмам хранения по мере их появления.
Однако Django может обновлять только пароли, использующие алгоритмы, упомянутые в PASSWORD_HASHERS, поэтому при обновлении до новых систем необходимо убедиться, что вы никогда не удаляете записи из этого списка. Если вы это сделаете, пользователи, использующие неуказанные алгоритмы, не смогут обновить свои пароли. Зашифрованные пароли будут обновлены при увеличении (или уменьшении) количества итераций PBKDF2 или раундов bcrypt.
Обратите внимание, что если все пароли в вашей базе данных не закодированы с помощью алгоритма по умолчанию, вы можете быть уязвимы к атаке на перечисление пользователей по таймингу из-за разницы во времени выполнения запроса входа в систему для пользователя с паролем, закодированным в нестандартном алгоритме, и времени выполнения запроса входа в систему для несуществующего пользователя (который использует алгоритм по умолчанию). Вы можете смягчить это, обновив старые хеши паролей.
Обновление паролей без необходимости входа в систему
Если у вас есть существующая база данных со старым слабым хешем, таким как MD5 или SHA1, вы можете захотеть самостоятельно обновить эти хеши вместо ожидания обновления при входе пользователя (что может никогда не произойти, если пользователь не вернется на ваш сайт). В этом случае вы можете использовать «оборачивающий» хешировщик паролей.
В этом примере мы мигрируем коллекцию хешей SHA1 на использование PBKDF2(SHA1(пароль)) и добавим соответствующий хешировщик паролей для проверки правильности введенного пользователем пароля при входе. Мы предполагаем, что мы используем встроенную User модель и что наш проект имеет accounts приложение. Вы можете изменить шаблон, чтобы он работал с любым алгоритмом или с пользовательской моделью.
Сначала добавим пользовательский хешировщик:
from django.contrib.auth.hashers import (
PBKDF2PasswordHasher, SHA1PasswordHasher,
)
class PBKDF2WrappedSHA1PasswordHasher(PBKDF2PasswordHasher):
algorithm = 'pbkdf2_wrapped_sha1'
def encode_sha1_hash(self, sha1_hash, salt, iterations=None):
return super(PBKDF2WrappedSHA1PasswordHasher, self).encode(sha1_hash, salt, iterations)
def encode(self, password, salt, iterations=None):
_, _, sha1_hash = SHA1PasswordHasher().encode(password, salt).split('$', 2)
return self.encode_sha1_hash(sha1_hash, salt, iterations)
Миграция данных может выглядеть примерно так:
from django.db import migrations
from ..hashers import PBKDF2WrappedSHA1PasswordHasher
def forwards_func(apps, schema_editor):
User = apps.get_model('auth', 'User')
users = User.objects.filter(password__startswith='sha1$')
hasher = PBKDF2WrappedSHA1PasswordHasher()
for user in users:
algorithm, salt, sha1_hash = user.password.split('$', 2)
user.password = hasher.encode_sha1_hash(sha1_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.PBKDF2WrappedSHA1PasswordHasher',
]
Включите в этот список все другие хешировщики, используемые вашим сайтом.
Включенные хешировщики
Полный список хешировщиков, включенных в 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.SHA1PasswordHasher',
'django.contrib.auth.hashers.MD5PasswordHasher',
'django.contrib.auth.hashers.UnsaltedSHA1PasswordHasher',
'django.contrib.auth.hashers.UnsaltedMD5PasswordHasher',
'django.contrib.auth.hashers.CryptPasswordHasher',
]
Соответствующие имена алгоритмов:
pbkdf2_sha256pbkdf2_sha1argon2bcrypt_sha256bcryptsha1md5unsalted_sha1unsalted_md5crypt
Написание собственного хешировщика паролей
Если вы пишете собственный хешировщик паролей, содержащий коэффициент сложности, такой как количество итераций, вы должны реализовать метод harden_runtime(self, password, encoded) для устранения разрыва во времени выполнения между коэффициентом сложности, указанным в encoded пароле, и коэффициентом сложности по умолчанию хешировщика. Это предотвращает атаку на перечисление пользователей по таймингу из-за разницы во времени выполнения запроса входа в систему для пользователя с паролем, закодированным со старым коэффициентом сложности, и несуществующего пользователя (который использует коэффициент сложности по умолчанию хешировщика).
Взяв PBKDF2 в качестве примера, если encoded содержит 20 000 итераций, а коэффициент сложности по умолчанию хешировщика iterations равен 30 000, метод должен выполнить password ещё 10 000 итераций PBKDF2.
Если у вашего хешировщика нет коэффициента сложности, реализуйте метод как бездействие (pass).
Ручное управление паролем пользователя
Модуль django.contrib.auth.hashers предоставляет набор функций для создания и проверки хэшированных паролей. Вы можете использовать их независимо от модели User.
-
check_password(password, encoded)[source] -
Если вы хотите вручную аутентифицировать пользователя, сравнив текстовый пароль с хэшированным паролем в базе данных, используйте удобную функцию
check_password(). Она принимает два аргумента: текстовый пароль для проверки и полное значение поляpasswordпользователя в базе данных для проверки, и возвращаетTrueесли они совпадают,Falseв противном случае.
-
make_password(password, salt=None, hasher='default')[source] -
Создаёт хэшированный пароль в формате, используемом этим приложением. Она принимает один обязательный аргумент: пароль в текстовом формате. По желанию, вы можете указать соль и алгоритм хеширования для использования, если вы не хотите использовать значения по умолчанию (первая запись в настройке
PASSWORD_HASHERS). См. Включенные хешировщики для имени алгоритма каждого хешировщика. Если аргумент password равенNone, возвращается непригодный пароль (такой, который никогда не будет принятcheck_password()).
-
is_password_usable(encoded_password)[source] -
Проверяет, является ли заданная строка хэшированным паролем, который можно проверить с помощью
check_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, который проверяет, не встречается ли пароль в списке общих паролей. По умолчанию он сравнивает с включённым списком из 1000 общих паролей. -
NumericPasswordValidator, который проверяет, не состоит ли пароль полностью из цифр.
Для UserAttributeSimilarityValidator и CommonPasswordValidator в этом примере мы просто используем параметры по умолчанию. NumericPasswordValidator не имеет настроек.
Тексты справки и любые ошибки от валидаторов паролей всегда возвращаются в порядке их перечисления в AUTH_PASSWORD_VALIDATORS.
Включённые валидаторы
Django включает четыре валидатора:
-
class MinimumLengthValidator(min_length=8)[source] -
Проверяет, соответствует ли пароль минимальной длине. Минимальную длину можно настроить с помощью параметра
min_length.
-
class UserAttributeSimilarityValidator(user_attributes=DEFAULT_USER_ATTRIBUTES, max_similarity=0.7)[source] -
Проверяет, достаточно ли отличается пароль от определённых атрибутов пользователя.
Параметр
user_attributesдолжен быть итерируемым списком имён атрибутов пользователя для сравнения. Если этот аргумент не указан, используется значение по умолчанию:'username', 'first_name', 'last_name', 'email'. Атрибуты, которых нет, игнорируются.Минимальное сходство отклоняемого пароля можно установить в диапазоне от 0 до 1 с помощью параметра
max_similarity. Значение 0 отклоняет все пароли, а значение 1 отклоняет только пароли, идентичные значению атрибута.
-
class CommonPasswordValidator(password_list_path=DEFAULT_PASSWORD_LIST_PATH)[source] -
Проверяет, является ли пароль распространённым. По умолчанию, он проверяет его по списку из 1000 распространённых паролей, созданных Марком Бернеттом.
Параметр
password_list_pathможно установить на путь к пользовательскому файлу с распространёнными паролями. Этот файл должен содержать один пароль на строке и может быть текстовым или сжатым (gzip).
-
class NumericPasswordValidator[source] -
Проверяет, не состоит ли пароль полностью из цифр.
Интеграция проверки
В django.contrib.auth.password_validation есть несколько функций, которые можно вызвать из собственных форм или другого кода для интеграции проверки паролей. Это может быть полезно, если вы используете пользовательские формы для установки паролей или если у вас есть вызовы API, которые позволяют устанавливать пароли.
-
validate_password(password, user=None, password_validators=None)[source] -
Проверяет пароль. Если все валидаторы считают пароль корректным, возвращает
None. Если один или несколько валидаторов отклоняют пароль, генерирует исключениеValidationErrorсо всеми сообщениями об ошибках от валидаторов.Объект
userявляется необязательным: если он не предоставлен, некоторые валидаторы могут не иметь возможности выполнить проверку и принять любой пароль.
-
password_changed(password, user=None, password_validators=None)[source] -
Сообщает всем валидаторам, что пароль был изменён. Это может использоваться валидаторами, предотвращающими повторное использование пароля. Это следует вызывать после успешного изменения пароля.
Для подклассов
AbstractBaseUser, поле пароля будет помечено как «изменённое» при вызовеset_password(), что запускает вызовpassword_changed()после сохранения пользователя.
-
password_validators_help_texts(password_validators=None)[source] -
Возвращает список текстов справки всех валидаторов. Они объясняют требования к паролю пользователю.
-
password_validators_help_text_html(password_validators=None) -
Возвращает HTML-строку со всеми текстами справки в
<ul>. Это полезно при добавлении проверки паролей в формы, так как вы можете передать вывод напрямую в параметрhelp_textполя формы.
-
get_password_validators(validator_config)[source] -
Возвращает набор объектов валидаторов на основе параметра
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 ugettext as _
class MinimumLengthValidator(object):
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/1.11/topics/auth/passwords/