Django: Забудьте о username! Аутентификация по Email или имени пользователя – легко!

В мире веб-разработки, гибкость и удобство пользовательской аутентификации играют ключевую роль. Django, мощный Python веб-фреймворк, предоставляет широкие возможности для настройки системы аутентификации. В этой статье мы рассмотрим, как реализовать аутентификацию, позволяющую пользователям входить в систему, используя как свой email, так и имя пользователя. Это повышает удобство использования и гибкость системы.

Основы аутентификации в Django: Стандартный подход и его ограничения

Стандартная аутентификация Django: что это?

По умолчанию, Django использует username в качестве основного идентификатора для аутентификации. Это простой и проверенный подход, который, однако, имеет свои ограничения.

Проблемы с использованием username как основного идентификатора.

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

Создание кастомной модели пользователя для аутентификации по Email или username

Настройка settings.py для использования кастомной модели пользователя

Чтобы переопределить стандартную модель пользователя, необходимо указать путь к вашей кастомной модели в settings.py:

AUTH_USER_MODEL = 'your_app.YourCustomUser'

Замените your_app.YourCustomUser на путь к вашей модели.

Реализация кастомной модели пользователя: поля, методы, особенности.

Пример кастомной модели пользователя:

from django.contrib.auth.models import AbstractBaseUser, BaseUserManager, PermissionsMixin
from django.db import models

class CustomUserManager(BaseUserManager):
    def create_user(self, email, username, password=None):
        if not email:
            raise ValueError('У пользователя должен быть email address')
        if not username:
            raise ValueError('У пользователя должно быть username')

        user = self.model(
            email=self.normalize_email(email),
            username=username,
        )

        user.set_password(password)
        user.save(using=self._db)
        return user

    def create_superuser(self, email, username, password):
        user = self.create_user(
            email=self.normalize_email(email),
            username=username,
            password=password,
        )
        user.is_admin = True
        user.is_staff = True
        user.is_superuser = True
        user.save(using=self._db)
        return user


class CustomUser(AbstractBaseUser, PermissionsMixin):
    email = models.EmailField(verbose_name='email address', max_length=255, unique=True)
    username = models.CharField(max_length=30, unique=True)
    is_active = models.BooleanField(default=True)
    is_staff = models.BooleanField(default=False)
    is_admin = models.BooleanField(default=False)

    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = ['username']

    objects = CustomUserManager()

    def __str__(self):
        return self.email

    def has_perm(self, perm, obj=None):
        return self.is_admin

    def has_module_perms(self, app_label):
        return True

В этой модели:

  • email используется как основной идентификатор (USERNAME_FIELD).

  • username также сохраняется.

  • Необходимо определить CustomUserManager для создания пользователей.

Настройка аутентификации: Backend и формы Django

Создание custom authentication backend для email/username аутентификации.

Создайте файл authentication.py (или другое имя) в вашем приложении и добавьте следующий код:

from django.contrib.auth.backends import ModelBackend
from django.contrib.auth import get_user_model
from django.db.models import Q

class EmailOrUsernameModelBackend(ModelBackend):
    def authenticate(self, request, username=None, password=None, **kwargs):
        UserModel = get_user_model()
        try:
            user = UserModel.objects.get(Q(username__iexact=username) | Q(email__iexact=username))
        except UserModel.DoesNotExist:
            return None
        else:
            if user.check_password(password):
                return user
        return None

Этот backend пытается аутентифицировать пользователя сначала по username, затем по email.

Реклама

Добавьте backend в settings.py:

AUTHENTICATION_BACKENDS = [
    'your_app.authentication.EmailOrUsernameModelBackend',
    'django.contrib.auth.backends.ModelBackend', # Keep default ModelBackend
]

Переопределение форм Django для логина и регистрации: реализация валидации.

Необходимо создать кастомные формы аутентификации для работы с email и username. Например, форма логина:

from django import forms

class LoginForm(forms.Form):
    username = forms.CharField(label='Email or Username')
    password = forms.CharField(widget=forms.PasswordInput)

Реализация логики аутентификации на практике: примеры кода

Пример кода: форма логина с использованием email или username.

Во view:

from django.shortcuts import render, redirect
from django.contrib.auth import authenticate, login
from .forms import LoginForm

def login_view(request):
    if request.method == 'POST':
        form = LoginForm(request.POST)
        if form.is_valid():
            username = form.cleaned_data['username']
            password = form.cleaned_data['password']
            user = authenticate(request, username=username, password=password)
            if user is not None:
                login(request, user)
                return redirect('home') # Replace 'home' with your home page URL
            else:
                form.add_error(None, 'Неверный email/username или пароль')
    else:
        form = LoginForm()
    return render(request, 'login.html', {'form': form})

Пример кода: регистрация нового пользователя с подтверждением email.

Регистрация включает отправку email для подтверждения. Для реализации этого функционала, рекомендуется использовать celery и redis.

from django.shortcuts import render, redirect
from .forms import RegistrationForm
from django.contrib.auth import get_user_model
from django.contrib.sites.shortcuts import get_current_site
from django.utils.encoding import force_bytes, force_str
from django.utils.http import urlsafe_base64_encode, urlsafe_base64_decode
from .tokens import account_activation_token
from django.core.mail import EmailMessage

def register_view(request):
    if request.method == 'POST':
        form = RegistrationForm(request.POST)
        if form.is_valid():
            user = form.save(commit=False)
            user.is_active = False
            user.save()
            current_site = get_current_site(request)
            mail_subject = 'Активируйте свой аккаунт.'
            message = render_to_string('acc_active_email.html', {
                'user': user,
                'domain': current_site.domain,
                'uid':urlsafe_base64_encode(force_bytes(user.pk)),
                'token': account_activation_token.make_token(user),
            })
            to_email = form.cleaned_data.get('email')
            email = EmailMessage(
                        mail_subject, message, to=[to_email]
            )
            email.send()
            return HttpResponse('Пожалуйста, подтвердите свой email, чтобы завершить регистрацию!')
    else:
        form = RegistrationForm()
    return render(request, 'register.html', {'form': form})

Безопасность и лучшие практики при аутентификации по Email/username

Хеширование паролей и защита от атак (XSS, CSRF, brute-force).

  • Django автоматически использует надежное хеширование паролей.

  • Защита от XSS и CSRF атак обеспечивается встроенными средствами Django (CSRF middleware).

  • Для защиты от brute-force атак рекомендуется использовать rate limiting и CAPTCHA.

Рекомендации по улучшению пользовательского опыта и дополнительные возможности (например, сброс пароля).

  • Реализуйте функцию сброса пароля по email.

  • Предоставьте пользователям возможность изменить свои данные (email, username).

  • Используйте понятные сообщения об ошибках.

Заключение

Реализация аутентификации по email или имени пользователя в Django позволяет создать более гибкую и удобную систему аутентификации. Использование кастомной модели пользователя и authentication backend дает полный контроль над процессом аутентификации. Не забывайте о безопасности и удобстве пользователя при реализации этой функциональности. Django предоставляет все необходимые инструменты для достижения этой цели.


Добавить комментарий