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

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

Razilator

В 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'
]

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

Вход по логину
Вход по логину
Вход по логину работает
Вход по логину работает
Вход по email
Вход по email
Вход по email работает
Вход по email работает
;