💻 Примеры — Урок 40

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

⚡ Минимальный пример: защищённый эндпоинт с TokenAuthentication

# settings.py
INSTALLED_APPS = [..., 'rest_framework', 'rest_framework.authtoken']
REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': ['rest_framework.authentication.TokenAuthentication'],
    'DEFAULT_PERMISSION_CLASSES': ['rest_framework.permissions.IsAuthenticated'],
}

# views.py
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.permissions import IsAuthenticated

class MeView(APIView):
    permission_classes = [IsAuthenticated]

    def get(self, request):
        return Response({"username": request.user.username})

# urls.py
from rest_framework.authtoken.views import obtain_auth_token
urlpatterns = [
    path('api/token/', obtain_auth_token),
    path('api/me/', MeView.as_view()),
]

Пример 1: BasicAuthentication

Простейшая настройка для тестирования — только с HTTPS в production.

settings.py

# settings.py
REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': [
        'rest_framework.authentication.BasicAuthentication',
    ],
    'DEFAULT_PERMISSION_CLASSES': [
        'rest_framework.permissions.IsAuthenticated',
    ],
}

views.py

# views.py
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.authentication import BasicAuthentication
from rest_framework.permissions import IsAuthenticated

class ProtectedDataView(APIView):
    authentication_classes = [BasicAuthentication]
    permission_classes = [IsAuthenticated]

    def get(self, request):
        return Response({
            "message": "Hello, authenticated user!",
            "user": request.user.username,
        })

urls.py

# urls.py
from django.urls import path
from .views import ProtectedDataView

urlpatterns = [
    path('protected/', ProtectedDataView.as_view(), name='protected-data'),
]

Тестирование через Postman

  1. Создайте GET-запрос к http://127.0.0.1:8000/protected/
  2. Вкладка Authorization → Type: Basic Auth
  3. Введите Username и Password
  4. Postman автоматически добавит заголовок Authorization: Basic dXNlcjpwYXNz
⚠️ В браузере можно передать учётные данные через URL: http://alice:secret@127.0.0.1:8000/protected/ — только для тестирования, небезопасно.

Пример 2: TokenAuthentication — полный цикл

Получение токена через POST-запрос и использование в защищённых эндпоинтах.

settings.py

# settings.py
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'rest_framework',
    'rest_framework.authtoken',  # ← обязательно
    'myapp',
]

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': [
        'rest_framework.authentication.TokenAuthentication',
    ],
    'DEFAULT_PERMISSION_CLASSES': [
        'rest_framework.permissions.IsAuthenticated',
    ],
}

Миграции

python manage.py migrate
# Создаёт таблицу authtoken_token в базе данных

views.py

# views.py
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.authentication import TokenAuthentication
from rest_framework.permissions import IsAuthenticated

class ProtectedDataView(APIView):
    authentication_classes = [TokenAuthentication]
    permission_classes = [IsAuthenticated]

    def get(self, request):
        return Response({
            "message": "Hello, authenticated user!",
            "user": request.user.username,
            "email": request.user.email,
        })

urls.py

# urls.py
from django.urls import path
from rest_framework.authtoken.views import obtain_auth_token
from .views import ProtectedDataView

urlpatterns = [
    path('api-token-auth/', obtain_auth_token, name='api_token_auth'),
    path('protected/', ProtectedDataView.as_view(), name='protected-data'),
]

Шаги тестирования через Postman

Шаг 1: Получение токена

  1. Метод: POST, URL: http://127.0.0.1:8000/api-token-auth/
  2. Body → form-data: username=admin, password=secret123
  3. Нажмите Send. Ответ: {"token": "e282c0176725bc6cca14396b5b7ab9affc440244"}

Шаг 2: Использование токена

  1. Метод: GET, URL: http://127.0.0.1:8000/protected/
  2. Headers: Authorization: Token e282c0176725bc6cca14396b5b7ab9affc440244
  3. Нажмите Send. Ответ: {"message": "Hello, authenticated user!", "user": "admin"}

Пример 3: JWT (Simple JWT)

Современный подход с access + refresh токенами.

Установка

pip install djangorestframework-simplejwt

settings.py

# settings.py
from datetime import timedelta

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': [
        'rest_framework_simplejwt.authentication.JWTAuthentication',
    ],
    'DEFAULT_PERMISSION_CLASSES': [
        'rest_framework.permissions.IsAuthenticated',
    ],
}

SIMPLE_JWT = {
    'ACCESS_TOKEN_LIFETIME': timedelta(minutes=5),
    'REFRESH_TOKEN_LIFETIME': timedelta(days=1),
}

urls.py

# urls.py
from django.urls import path
from rest_framework_simplejwt.views import TokenObtainPairView, TokenRefreshView
from .views import ProtectedDataView

urlpatterns = [
    path('api/token/', TokenObtainPairView.as_view(), name='token_obtain_pair'),
    path('api/token/refresh/', TokenRefreshView.as_view(), name='token_refresh'),
    path('api/protected/', ProtectedDataView.as_view(), name='protected'),
]

views.py

# views.py
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.permissions import IsAuthenticated

class ProtectedDataView(APIView):
    permission_classes = [IsAuthenticated]

    def get(self, request):
        return Response({
            "message": "Hello, authenticated user!",
            "user": request.user.username,
        })

Тестирование через Postman

Шаг 1: Получение JWT

  1. POST http://127.0.0.1:8000/api/token/
  2. Body → form-data: username=admin, password=secret123
  3. Ответ: {"access": "eyJhbGci...", "refresh": "eyJhbGci..."}

Шаг 2: Доступ к защищённому ресурсу

  1. GET http://127.0.0.1:8000/api/protected/
  2. Headers: Authorization: Bearer eyJhbGciOiJIUzI1NiIs...
  3. Ответ: {"message": "Hello, authenticated user!", "user": "admin"}

Шаг 3: Обновление истёкшего токена

  1. POST http://127.0.0.1:8000/api/token/refresh/
  2. Body → form-data: refresh=eyJhbGci... (refresh-токен)
  3. Ответ: {"access": "eyJhbGci... (новый access-токен)"}

Пример 4: смешанная аутентификация и разные разрешения

# views.py — несколько представлений с разными правами
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.permissions import IsAuthenticated, IsAdminUser, AllowAny, IsAuthenticatedOrReadOnly

class PublicNewsView(APIView):
    """Новости доступны всем без аутентификации"""
    permission_classes = [AllowAny]

    def get(self, request):
        return Response({"news": ["Новость 1", "Новость 2"]})


class UserProfileView(APIView):
    """Профиль — только для аутентифицированных"""
    permission_classes = [IsAuthenticated]

    def get(self, request):
        return Response({
            "username": request.user.username,
            "email": request.user.email,
        })


class AdminDashboardView(APIView):
    """Дашборд — только для staff-пользователей"""
    permission_classes = [IsAdminUser]

    def get(self, request):
        return Response({"stats": {"users": 42, "posts": 128}})


class ArticleView(APIView):
    """Статьи: читать могут все, писать — только авторизованные"""
    permission_classes = [IsAuthenticatedOrReadOnly]

    def get(self, request):
        return Response({"articles": ["Статья 1", "Статья 2"]})

    def post(self, request):
        # Сюда попадут только аутентифицированные
        return Response({"created": request.data.get("title")}, status=201)