Аутентификация в Django

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

Базовые настройки в settings.py

 1# Настройки аутентификации
 2AUTHENTICATION_BACKENDS = [
 3    'django.contrib.auth.backends.ModelBackend',
 4]
 5
 6# Настройки сессий
 7SESSION_COOKIE_AGE = 1209600  # 2 недели в секундах
 8SESSION_EXPIRE_AT_BROWSER_CLOSE = False
 9SESSION_SAVE_EVERY_REQUEST = True
10
11# Настройки входа
12LOGIN_URL = '/accounts/login/'
13LOGIN_REDIRECT_URL = '/dashboard/'
14LOGOUT_REDIRECT_URL = '/'
15
16# Настройки паролей
17AUTH_PASSWORD_VALIDATORS = [
18    {
19        'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
20    },
21    {
22        'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
23        'OPTIONS': {
24            'min_length': 8,
25        }
26    },
27    {
28        'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
29    },
30    {
31        'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
32    },
33]

Базовые URLs для аутентификации

 1from django.contrib.auth import views as auth_views
 2from django.urls import path
 3
 4urlpatterns = [
 5    # Встроенные views для аутентификации
 6    path('login/', auth_views.LoginView.as_view(template_name='registration/login.html'), name='login'),
 7    path('logout/', auth_views.LogoutView.as_view(), name='logout'),
 8    path('password_change/', auth_views.PasswordChangeView.as_view(), name='password_change'),
 9    path('password_change/done/', auth_views.PasswordChangeDoneView.as_view(), name='password_change_done'),
10    path('password_reset/', auth_views.PasswordResetView.as_view(), name='password_reset'),
11    path('password_reset/done/', auth_views.PasswordResetDoneView.as_view(), name='password_reset_done'),
12    path('reset/<uidb64>/<token>/', auth_views.PasswordResetConfirmView.as_view(), name='password_reset_confirm'),
13    path('reset/done/', auth_views.PasswordResetCompleteView.as_view(), name='password_reset_complete'),
14]

Создание кастомных форм аутентификации

 1from django import forms
 2from django.contrib.auth.forms import UserCreationForm, AuthenticationForm
 3from django.contrib.auth.models import User
 4
 5class CustomUserCreationForm(UserCreationForm):
 6    email = forms.EmailField(required=True)
 7    first_name = forms.CharField(max_length=30, required=True)
 8    last_name = forms.CharField(max_length=30, required=True)
 9
10    class Meta:
11        model = User
12        fields = ("username", "email", "first_name", "last_name", "password1", "password2")
13
14    def save(self, commit=True):
15        user = super().save(commit=False)
16        user.email = self.cleaned_data["email"]
17        user.first_name = self.cleaned_data["first_name"]
18        user.last_name = self.cleaned_data["last_name"]
19        if commit:
20            user.save()
21        return user
22
23class CustomAuthenticationForm(AuthenticationForm):
24    username = forms.CharField(
25        widget=forms.TextInput(attrs={'class': 'form-control', 'placeholder': 'Имя пользователя'})
26    )
27    password = forms.CharField(
28        widget=forms.PasswordInput(attrs={'class': 'form-control', 'placeholder': 'Пароль'})
29    )

Кастомизация LoginView

 1from django.contrib.auth.views import LoginView
 2from django.urls import reverse_lazy
 3
 4class CustomLoginView(LoginView):
 5    template_name = 'registration/custom_login.html'
 6    form_class = CustomAuthenticationForm
 7    success_url = reverse_lazy('dashboard')
 8
 9    def get_success_url(self):
10        # Перенаправление в зависимости от роли пользователя
11        if self.request.user.is_staff:
12            return reverse_lazy('admin:index')
13        return reverse_lazy('dashboard')
14
15    def form_valid(self, form):
16        # Логирование успешного входа
17        response = super().form_valid(form)
18        # Можно добавить дополнительную логику
19        return response

Создание пользователей программно

 1from django.contrib.auth.models import User
 2from django.contrib.auth.hashers import make_password
 3
 4# Создание суперпользователя
 5def create_superuser():
 6    if not User.objects.filter(username='admin').exists():
 7        User.objects.create_superuser(
 8            username='admin',
 9            email='admin@example.com',
10            password='secure_password_123'
11        )
12
13# Создание обычного пользователя
14def create_user(username, email, password, **extra_fields):
15    if User.objects.filter(username=username).exists():
16        return None
17
18    user = User.objects.create_user(
19        username=username,
20        email=email,
21        password=password,
22        **extra_fields
23    )
24    return user
25
26# Создание пользователя с хешированным паролем
27def create_user_with_hashed_password(username, email, password):
28    user = User(
29        username=username,
30        email=email,
31        password=make_password(password)
32    )
33    user.save()
34    return user

Проверка аутентификации в views

 1from django.contrib.auth.decorators import login_required, user_passes_test
 2from django.contrib.auth.mixins import LoginRequiredMixin, UserPassesTestMixin
 3from django.shortcuts import render, redirect
 4from django.views.generic import TemplateView
 5
 6# Функция-декоратор для проверки аутентификации
 7@login_required(login_url='/accounts/login/')
 8def protected_view(request):
 9    return render(request, 'dashboard.html', {'user': request.user})
10
11# Декоратор с дополнительной проверкой
12def is_premium_user(user):
13    return hasattr(user, 'profile') and user.profile.is_premium
14
15@user_passes_test(is_premium_user, login_url='/upgrade/')
16def premium_content(request):
17    return render(request, 'premium_content.html')
18
19# Class-based view с проверкой аутентификации
20class DashboardView(LoginRequiredMixin, TemplateView):
21    template_name = 'dashboard.html'
22    login_url = '/accounts/login/'
23    redirect_field_name = 'next'
24
25    def get_context_data(self, **kwargs):
26        context = super().get_context_data(**kwargs)
27        context['user'] = self.request.user
28        return context
29
30# Проверка прав доступа
31class AdminOnlyView(UserPassesTestMixin, TemplateView):
32    template_name = 'admin_only.html'
33
34    def test_func(self):
35        return self.request.user.is_staff

Работа с сессиями

 1from django.contrib.auth import login, logout
 2from django.contrib.auth.models import AnonymousUser
 3
 4def session_management(request):
 5    # Проверка аутентификации
 6    if request.user.is_authenticated:
 7        # Пользователь аутентифицирован
 8        username = request.user.username
 9        user_id = request.user.id
10
11        # Проверка активности сессии
12        if request.session.get('last_activity'):
13            # Обновление времени последней активности
14            request.session['last_activity'] = timezone.now()
15
16    else:
17        # Анонимный пользователь
18        username = 'Anonymous'
19        user_id = None
20
21    # Установка пользовательских данных в сессию
22    request.session['user_preferences'] = {
23        'theme': 'dark',
24        'language': 'ru'
25    }
26
27    # Получение данных из сессии
28    theme = request.session.get('user_preferences', {}).get('theme', 'light')
29
30    return render(request, 'session_info.html', {
31        'username': username,
32        'user_id': user_id,
33        'theme': theme
34    })

Настройка безопасности

 1# Дополнительные настройки безопасности в settings.py
 2SECURE_BROWSER_XSS_FILTER = True
 3SECURE_CONTENT_TYPE_NOSNIFF = True
 4X_FRAME_OPTIONS = 'DENY'
 5
 6# Настройки CSRF
 7CSRF_COOKIE_SECURE = True
 8CSRF_COOKIE_HTTPONLY = True
 9
10# Настройки сессий
11SESSION_COOKIE_SECURE = True
12SESSION_COOKIE_HTTPONLY = True
13SESSION_COOKIE_SAMESITE = 'Lax'
14
15# Ограничение попыток входа
16LOGIN_ATTEMPT_LIMIT = 5
17LOGIN_ATTEMPT_TIMEOUT = 300  # 5 минут

Middleware для отслеживания активности

 1from django.utils import timezone
 2from django.contrib.auth import logout
 3from django.shortcuts import redirect
 4
 5class UserActivityMiddleware:
 6    def __init__(self, get_response):
 7        self.get_response = get_response
 8
 9    def __call__(self, request):
10        if request.user.is_authenticated:
11            # Обновление времени последней активности
12            request.user.last_activity = timezone.now()
13            request.user.save(update_fields=['last_activity'])
14
15            # Проверка истечения сессии
16            last_activity = request.session.get('last_activity')
17            if last_activity:
18                last_activity = timezone.datetime.fromisoformat(last_activity)
19                if (timezone.now() - last_activity).seconds > 3600:  # 1 час
20                    logout(request)
21                    return redirect('login')
22
23            request.session['last_activity'] = timezone.now().isoformat()
24
25        response = self.get_response(request)
26        return response

Кастомизация User модели

 1from django.contrib.auth.models import AbstractUser
 2from django.db import models
 3
 4class CustomUser(AbstractUser):
 5    # Дополнительные поля
 6    phone_number = models.CharField(max_length=15, blank=True)
 7    date_of_birth = models.DateField(null=True, blank=True)
 8    avatar = models.ImageField(upload_to='avatars/', blank=True)
 9
10    # Настройки для email как username
11    USERNAME_FIELD = 'email'
12    REQUIRED_FIELDS = ['username']
13
14    def get_full_name(self):
15        return f"{self.first_name} {self.last_name}".strip()
16
17    def get_short_name(self):
18        return self.first_name or self.username
19
20# В settings.py
21AUTH_USER_MODEL = 'your_app.CustomUser'

FAQ по аутентификации

Q: Как кастомизировать формы аутентификации?

A: Создай собственные формы, наследуясь от встроенных форм Django, и укажи их в LoginView через параметр form_class. Также можешь переопределить шаблоны.

Q: Как ограничить доступ к определенным страницам?

A: Используй декоратор @login_required для функций или LoginRequiredMixin для class-based views. Для более сложных проверок используй @user_passes_test.

Q: Как настроить автоматический выход по истечении времени?

A: Настрой SESSION_COOKIE_AGE в settings.py или создай middleware для отслеживания активности пользователя.

Q: Как добавить двухфакторную аутентификацию?

A: Используй библиотеку django-two-factor-auth или создай собственную реализацию с помощью middleware и дополнительных моделей.

Q: Как безопасно хранить пароли пользователей?

A: Django автоматически хеширует пароли. Настрой AUTH_PASSWORD_VALIDATORS для проверки сложности паролей.

Лучшие практики

  • Всегда используй встроенные формы и views Django для базовой функциональности
  • Настрой правильные redirect URLs после входа/выхода
  • Используй HTTPS в продакшене для защиты данных аутентификации
  • Логируй попытки входа для мониторинга безопасности
  • Регулярно обновляй зависимости Django для получения исправлений безопасности
  • Используй strong password validation
  • Настрой правильные настройки сессий для твоего приложения