Django: Как реализовать регистрацию пользователя с подтверждением email?

Подтверждение email — важный этап регистрации пользователей, повышающий безопасность и качество базы данных.

Зачем нужна верификация email при регистрации?

Верификация email необходима для:

  1. Подтверждения принадлежности email пользователю. Убеждаемся, что указанный адрес действительно принадлежит регистрирующемуся.
  2. Предотвращения регистрации ботов и фейковых аккаунтов. Снижает количество неактивных или вредоносных учетных записей.
  3. Повышения доставляемости email-рассылок. Гарантирует, что рассылки будут доходить до реальных пользователей.
  4. Восстановления доступа к аккаунту. Email используется для сброса пароля и других операций.

Обзор процесса: от регистрации до активации аккаунта

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

  1. Пользователь заполняет форму регистрации.
  2. Django генерирует уникальный токен.
  3. Django отправляет email с ссылкой, содержащей токен.
  4. Пользователь переходит по ссылке.
  5. Django проверяет токен и активирует аккаунт.
  6. Пользователь перенаправляется на страницу приветствия.

Необходимые пакеты и настройки Django для работы с email

Для работы с email в Django необходимо настроить:

  • EMAIL_BACKEND — определяет, какой бэкенд использовать для отправки email (SMTP, консоль, файл и т. д.).
  • EMAIL_HOST, EMAIL_PORT, EMAIL_HOST_USER, EMAIL_HOST_PASSWORD — параметры SMTP-сервера (если используется).
  • EMAIL_USE_TLS или EMAIL_USE_SSL — параметры шифрования соединения.
  • DEFAULT_FROM_EMAIL — email-адрес, от которого отправляются письма.

Также может понадобиться библиотека django.contrib.sites для правильной генерации URL.

Создание модели пользователя и формы регистрации

Расширение стандартной модели пользователя Django (если требуется)

Если необходимо добавить дополнительные поля к стандартной модели User, создайте свою модель, наследуясь от AbstractUser или AbstractBaseUser.

from django.contrib.auth.models import AbstractUser
from django.db import models

class CustomUser(AbstractUser):
    # Дополнительные поля
    phone_number = models.CharField(max_length=15, blank=True)
    is_active = models.BooleanField(default=False) # Добавляем поле is_active

    def __str__(self):
        return self.username

Обязательно укажите свою модель пользователя в settings.py:

AUTH_USER_MODEL = 'your_app.CustomUser'

Разработка формы регистрации с необходимыми полями

Создайте форму регистрации, используя forms.Form или forms.ModelForm.

from django import forms
from .models import CustomUser

class RegistrationForm(forms.ModelForm):
    password = forms.CharField(widget=forms.PasswordInput)
    password_confirm = forms.CharField(widget=forms.PasswordInput)

    class Meta:
        model = CustomUser
        fields = ('username', 'email', 'password')

    def clean(self):
        cleaned_data = super().clean()
        password = cleaned_data.get('password')
        password_confirm = cleaned_data.get('password_confirm')

        if password != password_confirm:
            raise forms.ValidationError("Пароли не совпадают")

        return cleaned_data

Валидация данных формы и обработка ошибок

В форме необходимо валидировать введенные данные, например, проверять:

  • Совпадение паролей.
  • Уникальность username и email.
  • Корректность email-адреса.

Обрабатывайте ошибки валидации и выводите их пользователю.

Реклама

Генерация и отправка email с ссылкой для верификации

Создание уникального токена для подтверждения email

Используйте UUID или itsdangerous для генерации уникального токена.

import uuid

def generate_token() -> str:
    """Generates a unique token for email verification."""
    return str(uuid.uuid4())

Формирование URL-адреса с токеном верификации

Сформируйте URL-адрес, содержащий токен, который пользователь должен будет открыть.

from django.urls import reverse
from django.contrib.sites.models import Site

def build_verification_url(user_id: int, token: str) -> str:
    """Builds the verification URL with the token."""
    current_site = Site.objects.get_current()
    domain = current_site.domain
    path = reverse('verify_email', kwargs={'user_id': user_id, 'token': token})
    return f"https://{domain}{path}"

Настройка отправки email в Django (SMTP, консоль и др.)

Настройте параметры отправки email в settings.py. Для тестирования можно использовать бэкенд django.core.mail.backends.console.EmailBackend, который выводит письма в консоль.

Шаблоны email: дизайн и содержание письма с верификацией

Создайте шаблон email, содержащий ссылку для верификации. Используйте HTML для форматирования письма.

Пример шаблона (templates/registration/verification_email.html):

<p>Здравствуйте, {{ user.username }}!</p>
<p>Пожалуйста, перейдите по ссылке ниже, чтобы подтвердить свой email:</p>
<p><a href="{{ verification_url }}">{{ verification_url }}</a></p>

Обработка ссылки верификации и активация аккаунта

Создание view для обработки запроса по ссылке верификации

Создайте view, который будет обрабатывать запрос по ссылке верификации.

from django.shortcuts import render, redirect, get_object_or_404
from .models import CustomUser

def verify_email(request, user_id: int, token: str):
    """Verifies the user's email based on the provided token."""
    user = get_object_or_404(CustomUser, pk=user_id)
    if user.profile.email_token == token:
        user.is_active = True
        user.save()
        return redirect('verification_success')  # Redirect to success page
    else:
        return render(request, 'registration/verification_failed.html')

Проверка токена и активация аккаунта пользователя

В view проверьте токен и, если он верен, активируйте аккаунт пользователя (установите is_active = True).

Обработка случаев: токен истек, недействителен или пользователь уже активирован

Предусмотрите обработку следующих случаев:

  • Токен истек (если используется время жизни токена).
  • Токен недействителен (не соответствует токену пользователя).
  • Пользователь уже активирован.

Редирект пользователя после успешной активации

После успешной активации перенаправьте пользователя на страницу приветствия или страницу входа.

Безопасность и дополнительные улучшения

Защита от повторной отправки писем верификации

Защититесь от повторной отправки писем верификации, например, сохраняя время последней отправки и не отправляя письмо, если прошло слишком мало времени.

Ограничение времени действия ссылки верификации

Установите время действия ссылки верификации, чтобы предотвратить использование устаревших токенов.

import datetime
from django.utils import timezone

def is_token_expired(created_at: datetime.datetime, expiration_time: int = 24) -> bool:
    """Checks if the token has expired."""
    now = timezone.now()
    expiration_date = created_at + datetime.timedelta(hours=expiration_time)
    return now > expiration_date

Обработка ошибок и логирование

Обрабатывайте возможные ошибки и логируйте их для отладки и мониторинга.


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