Модель пользователя Django: какова цель смены пароля в методе save () - PullRequest
1 голос
/ 07 октября 2019

Иногда я хочу установить пароль программно. Я делаю следующее:

https://docs.djangoproject.com/en/2.2/topics/auth/default/#changing-passwords
You can also change a password programmatically, using set_password():

from django.contrib.auth.models import User
u = User.objects.get(username='john')
u.set_password('new pass')
u.save()

Я хотел посмотреть, как все реализовано в save (), когда мы запускаем u.save()

По сути, я пытаюсь понять используемый метод save ()в AbstractBaseUser

# ./.venv/lib/python3.7/site-packages/django/contrib/auth/base_user.py
class AbstractBaseUser(models.Model):
    password = models.CharField(_('password'), max_length=128)

    ........

    # Stores the raw password if set_password() is called so that it can
    # be passed to password_changed() after the model is saved.
    _password = None


    def save(self, *args, **kwargs):
        super().save(*args, **kwargs)
        if self._password is not None:
            password_validation.password_changed(self._password, self)
            self._password = None

    ........

    def set_password(self, raw_password):
        self.password = make_password(raw_password)
        self._password = raw_password

Здесь, в def save(self, *args, **kwargs):

super().save(*args, **kwargs)

, будет сохранен пароль, установленный set_password, перед следующими строками password_validation.password_changed, которые подтверждают пароль

ТакКакой смысл сначала сохранять пароль, а затем проверять его, потому что он уже внесен в базу данных.

1 Ответ

1 голос
/ 07 октября 2019

password_validation.password_changed не делает то, что вы думаете.

Фактическая проверка пароля выполняется перед сохранением объекта User путем вызова метода django.contrib.auth.password_validation.validate_password. Этот метод вызывает каждый валидатор в ваших настройках AUTH_PASSWORD_VALIDATORS и вызывает исключение при сбое любого из этих валидаторов. Это может быть любой вид проверки, например, достаточно ли сложен новый пароль или достаточно ли он отличается от имени пользователя.

В соответствии с документами :

По умолчанию валидаторы используются в формах для сброса или изменения паролей, а также в командах createuperuser и changepassword.

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

Итак, модель сохранения пользователя не проверяет пароль пользователя, а формы и команды. Если вы вручную устанавливаете пароль в коде где-то, убедитесь, что вы делаете эту проверку самостоятельно.

Так что же делает password_validation.password_changed(self._password, self)?

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

password_changed - это в основном способ для Djangoскажем всем валидаторам паролей: "Эй, обратите внимание, пароль пользователя был изменен на это значение, поэтому, если вам нужно по какой-то причине отслеживать его, сделайте это сейчас, потому что после этого я уничтожунепроизведенная версия этого пароля "

...