📖 Теория — Урок 40
⚡ Ключевые концепции урока
- Аутентификация — кто ты? Проверяет учётные данные. Выполняется первой.
- Авторизация — что тебе можно? Проверяет права. Выполняется после аутентификации.
- SessionAuthentication — куки + сессии Django; только для web-приложений
- BasicAuthentication — Base64(login:password) в заголовке Authorization; требует HTTPS
- TokenAuthentication —
Authorization: Token abc123; один токен на пользователя навсегда - JWT (SimpleJWT) —
Authorization: Bearer <token>; access (5 мин) + refresh (1 день) - IsAuthenticated — 401/403 для анонимов; IsAdminUser — только admin; AllowAny — без ограничений
- Неудачная аутентификация →
request.user = AnonymousUser, не ошибка - Неудачная авторизация →
403 Forbidden(PermissionDenied)
Часть 1: Аутентификация и авторизация — в чём разница
Сравнение концепций
| Аспект | Аутентификация | Авторизация |
|---|---|---|
| Вопрос | Кто ты? | Что тебе можно делать? |
| Действие | Проверяет учётные данные (токен, логин/пароль) | Определяет права доступа к ресурсам |
| Порядок | Первой (перед авторизацией) | После успешной аутентификации |
| Провал | request.user = AnonymousUser |
403 Forbidden (PermissionDenied) |
| DRF настройка | DEFAULT_AUTHENTICATION_CLASSES |
DEFAULT_PERMISSION_CLASSES |
Важность в реальных проектах
- Безопасность: защищает API от несанкционированного доступа и атак
- Управление доступом: контроль на основе ролей и прав пользователей
- Интеграция: поддержка различных методов для разных клиентов (web, mobile, API)
Часть 2: Порядок проверки в DRF
Django REST Framework обрабатывает каждый входящий запрос последовательно через два этапа.
Шаг 1: Аутентификация
- Инициализация: DRF перебирает все классы из
DEFAULT_AUTHENTICATION_CLASSESпоследовательно - Проверка учётных данных: каждый класс пытается извлечь и проверить данные (токен, сессию, заголовок). При успехе — устанавливается
request.userиrequest.auth - Провал: если ни один класс не сработал —
request.user = AnonymousUser. Провал аутентификации не вызывает немедленного отказа
Authorization: Token abc123. Если токен валиден — пользователь аутентифицирован. Нет токена или токен недействителен — request.user = AnonymousUser.
Шаг 2: Авторизация
- Инициализация: DRF определяет классы разрешений из
DEFAULT_PERMISSION_CLASSESили атрибутаpermission_classesпредставления - Проверка разрешений: каждый класс проверяет, есть ли у пользователя права. Разрешения работают на уровне представления (IsAuthenticated) или объекта (проверка владельца)
- Провал: если пользователь не имеет прав — выбрасывается
PermissionDenied→ HTTP 403 Forbidden
403 Forbidden.
Общая схема запроса
- Пользователь отправляет HTTP-запрос к API
- DRF проходит через все классы аутентификации → устанавливает
request.user - DRF проходит через все классы разрешений
- Если проверка разрешений успешна → обработка запроса продолжается
- Если провал разрешений →
PermissionDenied→ 403
Часть 3: Встроенные классы аутентификации DRF
1. SessionAuthentication
Использует сессии и куки Django для аутентификации пользователей. Основной метод для традиционных веб-приложений.
- Принцип работы: пользователь входит через форму логина; идентификатор сессии хранится в куках; каждый последующий запрос браузер автоматически отправляет куку
- Преимущества: встроен в Django, хорошо работает с форм-приложениями
- Ограничения: не подходит для мобильных приложений и «чистых» REST API, требует куки и сессии
2. BasicAuthentication
Простой метод: логин и пароль передаются в Base64 в заголовке каждого запроса.
- Принцип работы: клиент кодирует
username:passwordв Base64 и передаёт в заголовкеAuthorization: Basic dXNlcjpwYXNz - Преимущества: прост в реализации; не требует сессий или куки
- Ограничения: небезопасен без HTTPS (данные можно перехватить); учётные данные передаются при каждом запросе; не подходит для долгосрочной аутентификации
3. TokenAuthentication
Метод на основе токенов. После успешного входа сервер выдаёт токен; клиент отправляет его в заголовке каждого запроса.
- Принцип работы: токен хранится в базе данных и привязан к пользователю; заголовок:
Authorization: Token abc123def456... - Преимущества: подходит для REST API и мобильных приложений; аутентификация без сессий
- Ограничения: один токен на пользователя без срока действия — нужно управлять ротацией; требует app
rest_framework.authtoken
4. RemoteUserAuthentication
Для интеграции с внешними системами аутентификации (SSO, LDAP, Kerberos). Пользователь идентифицируется через HTTP-заголовок REMOTE_USER, установленный веб-сервером или прокси.
- Преимущества: удобен для корпоративных систем с единым входом (SSO)
- Ограничения: требует настройки внешнего веб-сервера; менее гибок для стандартных API
Часть 4: JWT-аутентификация (Simple JWT)
Структура JWT
JWT состоит из трёх частей, разделённых точками: header.payload.signature
| Часть | Содержание | Пример |
|---|---|---|
| Header | Метаданные: тип токена и алгоритм шифрования | {"alg":"HS256","typ":"JWT"} |
| Payload | Утверждения (claims): user_id, iat, exp, произвольные данные | {"user_id":1,"exp":1706000000} |
| Signature | Подпись для проверки целостности токена | HMAC-SHA256(header+payload, secret) |
Преимущества JWT перед TokenAuthentication
- Stateless: сервер не хранит сессии — вся информация в самом токене
- Масштабируемость: не нужна синхронизация сессий между серверами
- Access + Refresh токены: access (короткий срок) + refresh (долгий срок) для безопасной ротации
- Произвольные claims: можно включать роли, права доступа прямо в токен
- Снижение нагрузки на БД: проверка только подписи, без запроса к базе данных
Simple JWT в DRF
Библиотека djangorestframework-simplejwt — современное и гибкое решение для JWT в DRF.
pip install djangorestframework-simplejwt
Конфигурация в settings.py:
# settings.py
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework_simplejwt.authentication.JWTAuthentication',
],
}
from datetime import timedelta
SIMPLE_JWT = {
'ACCESS_TOKEN_LIFETIME': timedelta(minutes=5),
'REFRESH_TOKEN_LIFETIME': timedelta(days=1),
}
URL-маршруты для получения и обновления токенов:
# urls.py
from django.urls import path
from rest_framework_simplejwt.views import TokenObtainPairView, TokenRefreshView
urlpatterns = [
path('api/token/', TokenObtainPairView.as_view(), name='token_obtain_pair'),
path('api/token/refresh/', TokenRefreshView.as_view(), name='token_refresh'),
]
Использование в заголовке запроса:
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
Часть 5: Классы разрешений (Permissions)
Разрешения работают после аутентификации. Они определяют, имеет ли пользователь доступ к конкретному представлению или объекту.
Встроенные классы разрешений DRF
| Класс | Поведение |
|---|---|
AllowAny |
Доступ для всех, включая анонимных пользователей |
IsAuthenticated |
Только для аутентифицированных пользователей. Анонимы → 403 |
IsAdminUser |
Только для пользователей с is_staff=True |
IsAuthenticatedOrReadOnly |
Чтение (GET/HEAD/OPTIONS) — для всех; запись — только для авторизованных |
DjangoModelPermissions |
Права на основе стандартных Django-разрешений модели (add, change, delete, view) |
DjangoObjectPermissions |
Права на уровне конкретного объекта |
Настройка: глобально vs на уровне представления
# Глобальная настройка в settings.py
REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.IsAuthenticated',
],
}
# Переопределение на уровне конкретного представления
class PublicView(APIView):
permission_classes = [AllowAny]
...
class AdminOnlyView(APIView):
permission_classes = [IsAdminUser]
...
- 401 Unauthorized — пользователь не аутентифицирован (нет или неверный токен)
- 403 Forbidden — аутентифицирован, но нет прав на действие