Аутентификация в 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
- Настрой правильные настройки сессий для твоего приложения