JavaRush /Курсы /Модуль 3: Django /Практическое занятие по настройке аутентификации и разреш...

Практическое занятие по настройке аутентификации и разрешений

Модуль 3: Django
18 уровень , 9 лекция
Открыта

Давайте шаг за шагом создадим API с использованием аутентификации и кастомных разрешений. Это практическое занятие поможет нам не только закрепить изученные концепции, но и применить их в реальном проекте.

Цель практического занятия

  1. Реализовать вход через JWT и управление пользователями.
  2. Ограничить доступ к маршрутам на основе разрешений.
  3. Настроить кастомные классы разрешений для более гибкого контроля доступа.
  4. Провести тестирование аутентификации и разрешений.

На протяжении всего занятия мы будем добавлять функционал в наш учебный проект, который вы развивали ранее. Если вы вдруг "отстали от поезда", не переживайте — начнём с минимального набора требований.

Шаг 1: подготовка проекта

Если у вас ещё нет проекта с DRF, выполните следующие шаги, чтобы быстро создать его:

  1. Активируйте виртуальное окружение:

    source venv/bin/activate  # Linux/MacOS
    venv\Scripts\activate     # Windows
    
  2. Установите Django и DRF:

    pip install django djangorestframework
    
  3. Создайте новый проект:

    django-admin startproject myproject
    cd myproject
    
  4. Создайте приложение:

    python manage.py startapp myapp
    
  5. Зарегистрируйте приложение в settings.py:

    INSTALLED_APPS = [
        # ...
        'rest_framework',
        'myapp',
    ]
    

Теперь у нас есть всё необходимое для работы. Погнали дальше!

Шаг 2: установка и настройка JWT

В предыдущих лекциях мы обсуждали JWT и его преимущества. Сейчас настроим проект для работы с JWT.

  1. Установите библиотеку djangorestframework-simplejwt:

    pip install djangorestframework-simplejwt
    
  2. Настройте аутентификацию в проекте. Добавьте следующие параметры в settings.py:

    REST_FRAMEWORK = {
        'DEFAULT_AUTHENTICATION_CLASSES': [
            'rest_framework_simplejwt.authentication.JWTAuthentication',
        ],
    }
    
  3. Добавьте 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: создание защищённого маршрута

Добавим пример защищённого маршрута, к которому можно обращаться только после аутентификации.

  1. В 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": "Ты авторизован, добро пожаловать!"})
  2. Добавьте маршрут для этой вьюшки в myapp/urls.py:

    from django.urls import path
    from .views import ProtectedView
    
    urlpatterns = [
        path('protected/', ProtectedView.as_view(), name='protected'),
    ]
  3. Подключите маршруты приложения к основному файлу urls.py:

    from django.urls import include
    
    urlpatterns = [
        # ...
        path('api/', include('myapp.urls')),
    ]

Попробуйте обратиться к /api/protected/ без JWT. Вы должны получить ответ с кодом 401 (Unauthorized). Теперь добавьте токен в заголовок запроса, и защита пропустит вас.

Шаг 4: создание кастомного разрешения

Теперь давайте усложним задачу. Создадим кастомное разрешение, которое запрещает доступ к маршруту пользователям с email-адресами в домене example.com (привет спамерам!).

  1. В 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
  2. Обновите ProtectedView, чтобы использовать это разрешение:

    from .permissions import IsNotExampleDotComUser
    
    class ProtectedView(APIView):
        permission_classes = [IsNotExampleDotComUser]
    
        def get(self, request):
            return Response({"message": "Ты не спамер, добро пожаловать!"})

Теперь попробуйте протестировать маршрут /api/protected/ с пользователем, у которого email заканчивается на @example.com. Доступ будет запрещён.

Шаг 5: тестирование

Тестирование — это важно! Проверим, как работают наши маршруты и разрешения.

  1. Установите pytest и pytest-django:

    pip install pytest pytest-django
    
  2. Создайте файл 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
  3. Запустите тесты:

    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": "Это секретная страница для админов!"})

Практическое задание для самостоятельной работы

  1. Реализуйте новый маршрут, доступный только для администраторов.
  2. Создайте кастомное разрешение, которое запрещает доступ пользователям с датой регистрации старше 30 дней.
  3. Напишите тесты для всех добавленных маршрутов и разрешений.

Используйте предоставленные примеры как основу для своего кода. Но будьте внимательны: тесты не просто проверяют ваше приложение, они ещё и ваши "друзья", которые помогут избежать регрессий в будущем.

Теперь ваш API готов к использованию в реальных приложениях, и вы можете быть уверены, что безопасность на уровне доступа к данным находится под контролем. 🚀

1
Задача
Модуль 3: Django, 18 уровень, 9 лекция
Недоступна
Добавление разрешений к ViewSet
Добавление разрешений к ViewSet
1
Задача
Модуль 3: Django, 18 уровень, 9 лекция
Недоступна
Создание кастомного разрешения
Создание кастомного разрешения
3
Опрос
JWT (JSON Web Tokens), 18 уровень, 9 лекция
Недоступен
JWT (JSON Web Tokens)
JWT (JSON Web Tokens)
Комментарии (1)
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
Евгений Уровень 70
7 октября 2025
В опросе ошибка в последнем вопросе - Какой метод в классе TokenObtainPairView можно переопределить для изменения выдаваемого payload ? Валидатор считает: validate() Правильный ответ: get_token()