🐛 Типичные ошибки — Урок 40

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

⚡ Топ-5 ошибок при настройке аутентификации

  • Забыть добавить rest_framework.authtoken в INSTALLED_APPS → OperationalError: no such table
  • Не выполнить python manage.py migrate после добавления authtoken → та же ошибка
  • Использовать Token вместо Bearer в заголовке JWT → 401 Unauthorized
  • User.objects.create(password='...') вместо create_user() → пароль в открытом виде
  • BasicAuthentication без HTTPS в production → перехват учётных данных

Ошибка 1: Забытый rest_framework.authtoken в INSTALLED_APPS

Симптом

django.db.utils.OperationalError: no such table: authtoken_token

Причина

TokenAuthentication требует отдельного приложения rest_framework.authtoken, которое добавляет модель Token и таблицу в БД.

Неправильно

INSTALLED_APPS = [
    'rest_framework',
    # rest_framework.authtoken ЗАБЫТО
    'myapp',
]

Правильно

INSTALLED_APPS = [
    'rest_framework',
    'rest_framework.authtoken',  # ← обязательно
    'myapp',
]
# И затем:
# python manage.py migrate

Ошибка 2: Неправильный формат заголовка Authorization

Симптом

HTTP 401 Unauthorized
{"detail": "Authentication credentials were not provided."}

Причина

Путаница между схемами Token (DRF) и Bearer (JWT).

Неправильно

# При использовании TokenAuthentication:
Authorization: Bearer abc123def456

# При использовании JWTAuthentication:
Authorization: Token eyJhbGci...

Правильно

# TokenAuthentication:
Authorization: Token abc123def456

# JWTAuthentication (Simple JWT):
Authorization: Bearer eyJhbGci...

Ошибка 3: Создание пользователя с нехешированным паролем

Симптом

Пользователь создан, но не может войти — пароль хранится в открытом виде в БД.

Неправильно

from django.contrib.auth.models import User

# ← password сохраняется в открытом виде!
user = User.objects.create(
    username='alice',
    password='secret123'
)

Правильно

from django.contrib.auth.models import User

# create_user() хеширует пароль через PBKDF2
user = User.objects.create_user(
    username='alice',
    password='secret123',
    email='alice@example.com'
)

Ошибка 4: Смешение глобальных и локальных настроек

Симптом

Неожиданное поведение разрешений — одни представления требуют аутентификации, другие нет, хотя должны.

Неправильно

# settings.py — разрешено всем
REST_FRAMEWORK = {
    'DEFAULT_PERMISSION_CLASSES': [
        'rest_framework.permissions.AllowAny',  # ← опасно!
    ],
}

# views.py — забыли переопределить
class SecretView(APIView):
    # нет permission_classes — применится AllowAny
    def get(self, request):
        return Response({"secret": "data"})

Правильно

# settings.py — строго по умолчанию
REST_FRAMEWORK = {
    'DEFAULT_PERMISSION_CLASSES': [
        'rest_framework.permissions.IsAuthenticated',
    ],
}

# views.py — явно открываем публичные
class PublicView(APIView):
    permission_classes = [AllowAny]  # ← явное исключение
    ...

class SecretView(APIView):
    # наследует IsAuthenticated из глобальных
    def get(self, request):
        return Response({"secret": "data"})
Принцип безопасности: всегда используйте максимально строгие настройки по умолчанию. Открывайте доступ явно, а не закрывайте по необходимости.

Ошибка 5: BasicAuthentication в production без HTTPS

Симптом

API работает, но учётные данные можно перехватить сниффером. Base64 — не шифрование!

# Base64 легко декодировать:
import base64
base64.b64decode('YWxpY2U6c2VjcmV0MTIz').decode()
# 'alice:secret123'  ← учётные данные в открытом виде
⚠️ BasicAuthentication должен использоваться ТОЛЬКО с HTTPS. В production всегда применяйте TLS/SSL.

Ошибка 6: Неправильная конфигурация Simple JWT

Симптом

ImportError: cannot import name 'JWTAuthentication' from 'rest_framework'

Причина

Simple JWT — отдельная библиотека, импорт идёт не из rest_framework, а из rest_framework_simplejwt.

Неправильно

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': [
        # ← неверный модуль!
        'rest_framework.authentication.JWTAuthentication',
    ],
}

Правильно

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': [
        # ← правильный модуль
        'rest_framework_simplejwt.authentication.JWTAuthentication',
    ],
}

Ошибка 7: Отправка access-токена вместо refresh при обновлении

Симптом

HTTP 401
{"detail": "Token is invalid or expired", "code": "token_not_valid"}

Причина

Эндпоинт /api/token/refresh/ ожидает refresh-токен, а не access-токен.

Неправильно

# POST /api/token/refresh/
{
  "refresh": "eyJ... (access токен)"  # ← ошибка!
}

Правильно

# POST /api/token/refresh/
{
  "refresh": "eyJ... (refresh токен из /api/token/)"
}

# Ответ: {"access": "eyJ... (новый access токен)"}