📖 Теория — Урок 40

← К оглавлению урока

⚡ Ключевые концепции урока

  • Аутентификация — кто ты? Проверяет учётные данные. Выполняется первой.
  • Авторизация — что тебе можно? Проверяет права. Выполняется после аутентификации.
  • SessionAuthentication — куки + сессии Django; только для web-приложений
  • BasicAuthentication — Base64(login:password) в заголовке Authorization; требует HTTPS
  • TokenAuthenticationAuthorization: Token abc123; один токен на пользователя навсегда
  • JWT (SimpleJWT)Authorization: Bearer <token>; access (5 мин) + refresh (1 день)
  • IsAuthenticated — 401/403 для анонимов; IsAdminUser — только admin; AllowAny — без ограничений
  • Неудачная аутентификация → request.user = AnonymousUser, не ошибка
  • Неудачная авторизация → 403 Forbidden (PermissionDenied)

Часть 1: Аутентификация и авторизация — в чём разница

Аутентификация (Authentication) — процесс проверки подлинности пользователя или устройства, запрашивающего доступ к ресурсу. В контексте DRF это установление личности пользователя — например, путём предоставления токена или учётных данных.
Авторизация (Authorization) — процесс определения, имеет ли аутентифицированный пользователь право доступа к конкретным ресурсам или действиям. В DRF это осуществляется с помощью разрешений, которые контролируют доступ на основе ролей, прав и других критериев.

Сравнение концепций

Аспект Аутентификация Авторизация
Вопрос Кто ты? Что тебе можно делать?
Действие Проверяет учётные данные (токен, логин/пароль) Определяет права доступа к ресурсам
Порядок Первой (перед авторизацией) После успешной аутентификации
Провал request.user = AnonymousUser 403 Forbidden (PermissionDenied)
DRF настройка DEFAULT_AUTHENTICATION_CLASSES DEFAULT_PERMISSION_CLASSES

Важность в реальных проектах

  • Безопасность: защищает API от несанкционированного доступа и атак
  • Управление доступом: контроль на основе ролей и прав пользователей
  • Интеграция: поддержка различных методов для разных клиентов (web, mobile, API)

Часть 2: Порядок проверки в DRF

Django REST Framework обрабатывает каждый входящий запрос последовательно через два этапа.

Шаг 1: Аутентификация

  1. Инициализация: DRF перебирает все классы из DEFAULT_AUTHENTICATION_CLASSES последовательно
  2. Проверка учётных данных: каждый класс пытается извлечь и проверить данные (токен, сессию, заголовок). При успехе — устанавливается request.user и request.auth
  3. Провал: если ни один класс не сработал — request.user = AnonymousUser. Провал аутентификации не вызывает немедленного отказа
Пример: При использовании TokenAuthentication токен извлекается из заголовка Authorization: Token abc123. Если токен валиден — пользователь аутентифицирован. Нет токена или токен недействителен — request.user = AnonymousUser.

Шаг 2: Авторизация

  1. Инициализация: DRF определяет классы разрешений из DEFAULT_PERMISSION_CLASSES или атрибута permission_classes представления
  2. Проверка разрешений: каждый класс проверяет, есть ли у пользователя права. Разрешения работают на уровне представления (IsAuthenticated) или объекта (проверка владельца)
  3. Провал: если пользователь не имеет прав — выбрасывается PermissionDenied → HTTP 403 Forbidden
Пример: При использовании IsAuthenticated представление доступно только аутентифицированным пользователям. Анонимный пользователь получает 403 Forbidden.

Общая схема запроса

  1. Пользователь отправляет HTTP-запрос к API
  2. DRF проходит через все классы аутентификации → устанавливает request.user
  3. DRF проходит через все классы разрешений
  4. Если проверка разрешений успешна → обработка запроса продолжается
  5. Если провал разрешений → PermissionDenied → 403

Часть 3: Встроенные классы аутентификации DRF

1. SessionAuthentication

Использует сессии и куки Django для аутентификации пользователей. Основной метод для традиционных веб-приложений.

  • Принцип работы: пользователь входит через форму логина; идентификатор сессии хранится в куках; каждый последующий запрос браузер автоматически отправляет куку
  • Преимущества: встроен в Django, хорошо работает с форм-приложениями
  • Ограничения: не подходит для мобильных приложений и «чистых» REST API, требует куки и сессии

2. BasicAuthentication

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

  • Принцип работы: клиент кодирует username:password в Base64 и передаёт в заголовке Authorization: Basic dXNlcjpwYXNz
  • Преимущества: прост в реализации; не требует сессий или куки
  • Ограничения: небезопасен без HTTPS (данные можно перехватить); учётные данные передаются при каждом запросе; не подходит для долгосрочной аутентификации
⚠️ BasicAuthentication следует использовать исключительно с HTTPS. Без шифрования учётные данные передаются в открытом виде (Base64 ≠ шифрование).

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 (JSON Web Token) — компактный, URL-безопасный способ передачи утверждений между двумя сторонами. Используется для аутентификации в API без хранения сессий на сервере.

Структура 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 — аутентифицирован, но нет прав на действие
В DRF оба случая часто возвращают 403, если нет настроенной схемы аутентификации.