Давайте шаг за шагом создадим API с использованием аутентификации и кастомных разрешений. Это практическое занятие поможет нам не только закрепить изученные концепции, но и применить их в реальном проекте.
Цель практического занятия
- Реализовать вход через JWT и управление пользователями.
- Ограничить доступ к маршрутам на основе разрешений.
- Настроить кастомные классы разрешений для более гибкого контроля доступа.
- Провести тестирование аутентификации и разрешений.
На протяжении всего занятия мы будем добавлять функционал в наш учебный проект, который вы развивали ранее. Если вы вдруг "отстали от поезда", не переживайте — начнём с минимального набора требований.
Шаг 1: подготовка проекта
Если у вас ещё нет проекта с DRF, выполните следующие шаги, чтобы быстро создать его:
Активируйте виртуальное окружение:
source venv/bin/activate # Linux/MacOS venv\Scripts\activate # WindowsУстановите Django и DRF:
pip install django djangorestframeworkСоздайте новый проект:
django-admin startproject myproject cd myprojectСоздайте приложение:
python manage.py startapp myappЗарегистрируйте приложение в
settings.py:INSTALLED_APPS = [ # ... 'rest_framework', 'myapp', ]
Теперь у нас есть всё необходимое для работы. Погнали дальше!
Шаг 2: установка и настройка JWT
В предыдущих лекциях мы обсуждали JWT и его преимущества. Сейчас настроим проект для работы с JWT.
Установите библиотеку
djangorestframework-simplejwt:pip install djangorestframework-simplejwtНастройте аутентификацию в проекте. Добавьте следующие параметры в
settings.py:REST_FRAMEWORK = { 'DEFAULT_AUTHENTICATION_CLASSES': [ 'rest_framework_simplejwt.authentication.JWTAuthentication', ], }Добавьте URL для получения токенов. В
myproject/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'), ]
Теперь, чтобы получить JWT, нужно будет сделать POST-запрос на /api/token/ с логином и паролем пользователя.
Шаг 3: создание защищённого маршрута
Добавим пример защищённого маршрута, к которому можно обращаться только после аутентификации.
В
myapp/views.pyсоздайте простой APIView:from rest_framework.views import APIView from rest_framework.response import Response from rest_framework.permissions import IsAuthenticated class ProtectedView(APIView): permission_classes = [IsAuthenticated] def get(self, request): return Response({"message": "Ты авторизован, добро пожаловать!"})Добавьте маршрут для этой вьюшки в
myapp/urls.py:from django.urls import path from .views import ProtectedView urlpatterns = [ path('protected/', ProtectedView.as_view(), name='protected'), ]Подключите маршруты приложения к основному файлу
urls.py:from django.urls import include urlpatterns = [ # ... path('api/', include('myapp.urls')), ]
Попробуйте обратиться к /api/protected/ без JWT. Вы должны получить ответ с кодом 401 (Unauthorized). Теперь добавьте токен в заголовок запроса, и защита пропустит вас.
Шаг 4: создание кастомного разрешения
Теперь давайте усложним задачу. Создадим кастомное разрешение, которое запрещает доступ к маршруту пользователям с email-адресами в домене example.com (привет спамерам!).
В
myapp/permissions.pyсоздайте новый класс:from rest_framework.permissions import BasePermission class IsNotExampleDotComUser(BasePermission): def has_permission(self, request, view): # Проверяем email пользователя (если он авторизован) if request.user and request.user.is_authenticated: return not request.user.email.endswith('@example.com') return FalseОбновите
ProtectedView, чтобы использовать это разрешение:from .permissions import IsNotExampleDotComUser class ProtectedView(APIView): permission_classes = [IsNotExampleDotComUser] def get(self, request): return Response({"message": "Ты не спамер, добро пожаловать!"})
Теперь попробуйте протестировать маршрут /api/protected/ с пользователем, у которого email заканчивается на @example.com. Доступ будет запрещён.
Шаг 5: тестирование
Тестирование — это важно! Проверим, как работают наши маршруты и разрешения.
Установите
pytestиpytest-django:pip install pytest pytest-djangoСоздайте файл
tests/test_permissions.pyв приложенииmyapp:import pytest from rest_framework.test import APIClient from django.contrib.auth.models import User @pytest.mark.django_db def test_protected_view_success(): client = APIClient() user = User.objects.create_user(username='testuser', email='user@domain.com', password='testpass') client.force_authenticate(user=user) response = client.get('/api/protected/') assert response.status_code == 200 assert response.data['message'] == "Ты не спамер, добро пожаловать!" @pytest.mark.django_db def test_protected_view_email_restricted(): client = APIClient() user = User.objects.create_user(username='spamuser', email='spam@example.com', password='testpass') client.force_authenticate(user=user) response = client.get('/api/protected/') assert response.status_code == 403 # ForbiddenЗапустите тесты:
pytest
Если всё работает, вы увидите зелёные галочки в выводе.
Шаг 6: применение разрешений к другим маршрутам
Теперь вы можете легко добавлять другие уровни защиты вашему API. Например, можно использовать встроенный IsAdminUser, чтобы разрешить доступ к определённым маршрутам только администраторам, или комбинировать несколько разрешений.
Пример комбинированного разрешения:
from rest_framework.permissions import IsAuthenticated, IsAdminUser
from rest_framework.decorators import api_view, permission_classes
@api_view(['GET'])
@permission_classes([IsAuthenticated, IsAdminUser])
def admin_only_view(request):
return Response({"message": "Это секретная страница для админов!"})
Практическое задание для самостоятельной работы
- Реализуйте новый маршрут, доступный только для администраторов.
- Создайте кастомное разрешение, которое запрещает доступ пользователям с датой регистрации старше 30 дней.
- Напишите тесты для всех добавленных маршрутов и разрешений.
Используйте предоставленные примеры как основу для своего кода. Но будьте внимательны: тесты не просто проверяют ваше приложение, они ещё и ваши "друзья", которые помогут избежать регрессий в будущем.
Теперь ваш API готов к использованию в реальных приложениях, и вы можете быть уверены, что безопасность на уровне доступа к данным находится под контролем. 🚀
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ