Django База [2023]: Авторизация по email и по логину (свой бекенд аутентификации) 👨‍💻 #41

Django Django База [2023]: Авторизация по email и по логину (свой бекенд аутентификации) 👨‍💻 #41


В Django можно настроить авторизацию по email и по логину одновременно. Для этого можно использовать стандартную модель пользователя Django. Но учтите, я советую вам сделать поле email уникальным, наследуясь от модели AbstractUser. В рамках курса я использую стандартную модель Django с профилем через связь один-к-одному.

Виды расширений пользовательской модели

Переопределение системы аутентификации Django

Давайте создадим файл backends.py в приложении system со следующим фрагментом кода:

modules/system/backends.py
from django.contrib.auth.backends import ModelBackend, get_user_model
from django.core.exceptions import MultipleObjectsReturned
from django.db.models import Q

UserModel = get_user_model()

class UserModelBackend(ModelBackend):
    """
    Переопределение авторизации
    """

    def authenticate(self, request, username=None, password=None, **kwargs):
        try:
            user = UserModel.objects.get(Q(username=username) | Q(email__iexact=username))
        except UserModel.DoesNotExist:
            return None
        except MultipleObjectsReturned:
            return UserModel.objects.filter(email=username).order_by('id').first()
        else:
            if user.check_password(password) and self.user_can_authenticate(user):
                return user

    def get_user(self, user_id):
        try:
            user = UserModel.objects.get(pk=user_id)
        except UserModel.DoesNotExist:
            return None

        return user if self.user_can_authenticate(user) else None

Этот код определяет специальный бэкэнд аутентификации UserModelBackend, который расширяет стандартный ModelBackend Django. Бэкэнд позволяет пользователю авторизоваться по username или по email.

Для начала он импортирует ModelBackend и функцию get_user_model() из Django. Затем он использует get_user_model(), чтобы получить модель пользователя, связанную с текущей конфигурацией Django.

Затем определены два метода: authenticate() и get_user().

Метод authenticate() вызывается при попытке аутентификации пользователя. Он ищет пользователя в базе данных, используя UserModel.objects.get(), и проверяет, соответствует ли введенный пароль тому, что хранится в базе данных. Если все верно, то пользователь возвращается.

Если пользователь не найден, то возвращается значение None. Если было найдено несколько пользователей, связанных с указанными username или email, то берется только первый, который найден.

Метод get_user() вызывается при обращении к объекту пользователя request.user. Если пользователь уже прошел аутентификацию, то Django запоминает его в request.user. Этот метод проверяет, что пользователь валидный, и возвращает объект User или None, в зависимости от результата проверки.

Таким образом, код предоставляет более гибкий механизм аутентификации для приложения Django.

Добавление новых изменений в конфигурационный файл

Далее нам необходимо добавить наш улучшенный бекенд в settings.py, для этого добавим в любое место конфигурации:

backend/settings.py
AUTHENTICATION_BACKENDS = [
    'modules.system.backends.UserModelBackend'
]

Проверка работы нового бекенда

Django База [2023]: Авторизация по email и по логину (свой бекенд аутентификации) 👨‍💻 #41
Вход по логину
Django База [2023]: Авторизация по email и по логину (свой бекенд аутентификации) 👨‍💻 #41
Вход по логину работает
Django База [2023]: Авторизация по email и по логину (свой бекенд аутентификации) 👨‍💻 #41
Вход по email
Django База [2023]: Авторизация по email и по логину (свой бекенд аутентификации) 👨‍💻 #41
Вход по email работает