Учебник по Джанго JWT

Что такое JWT

JWT (Json Web Token) — это стандарт, определяющий способ передачи защищенной информации с помощью токенов.

JWT обычно используются для аутентификации и авторизации в веб-приложениях, API-интерфейсах и архитектурах микросервисов, включая внешние приложения, созданные с использованием таких технологий, как Next.js, Angular или React. JWT предоставляют безопасные средства передачи токенов аутентификации между клиентом и сервером.

JWT могут быть подписаны публично или конфиденциально. Стандартный JWT выглядит следующим образом:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.
SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

Как видите, его структура состоит из 3 частей, разделенных точкой (.), а именно:

  • заголовок
  • полезная нагрузка
  • подпись

Заголовок:

Заголовок — это первая часть токена JWT, и он определяет алгоритм, используемый для подписи и проверки подписи. Алгоритмы подписи могут включать подпись RSA, HMAC-SHA256, HMAC-SHA512 и другие.

Полезная нагрузка:

Полезная нагрузка — это вторая часть, и она содержит претензии. Претензия может включать в себя следующее:

  • Идентификатор пользователя.
  • Разрешения.
  • Время истечения.
  • Выпущено-вовремя.
  • Любые другие данные, требуемые приложением.

Подпись

Подпись и третья часть создаются путем объединения заголовка в кодировке base64, полезной нагрузки в кодировке base64 и секретного ключа. Подпись используется для проверки подлинности токена JWT.

Все три части кодируются Base64Url и объединяются с использованием точек («.») для формирования строки URL.

Когда пользователь входит на веб-сайт, он аутентифицируется, и сервер генерирует уникальный токен JWT в качестве ответа. Затем пользователь использует токен в последующих запросах, включая его в заголовок авторизации в формате Authorization: Bearer [JWT token].

Во время последующих запросов сервер будет постоянно проверять подлинность токена при каждом запросе.

Начиная

В этом разделе мы создадим приложение django и продемонстрируем, как генерируются токены JWT, когда пользователь аутентифицируется, и как ограничить доступ к определенным представлениям, когда пользователь не предоставляет токен.

Начнем с создания и активации новой виртуальной среды с помощью модуля venv.

python -m venv myenviron
source myenviron/bin/activate

Установите django, django rest framework и простой пакет JWT. Простой JWT обеспечивает простой в использовании механизм проверки подлинности для среды Django REST.

pip install  django djangorestframework djangorestframework-simplejwt

Создайте проект django с именем django_jwt и приложение с именем tokens.

django-admin startproject django_jwt
cd django_jwt
python manage.py startapp tokens

Добавьте платформу Django rest, пакет Simple JWT и приложение tokens в список INSTALLED_APPS в файле settings.py.

INSTALLED_APPS = [
   ......

    'rest_framework_simplejwt',
    'rest_framework',

    'tokens',
]

Затем добавьте rest_framework_simplejwt.authentication.JWTAuthentication в файл DEFAULT_AUTHENTICATION_CLASSES settings.py.

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': [
        'rest_framework_simplejwt.authentication.JWTAuthentication',
    ],
}

Платформа Django rest использует параметр DEFAULT_AUTHENTICATION_CLASSES, чтобы указать список классов аутентификации для аутентификации. Добавление rest_framework_simplejwt.authentication.JWTAuthentication configures Django Rest framework для использования JWT-аутентификации для вашего приложения.

Запустите миграцию, чтобы создать таблицы пользовательской базы данных по умолчанию. Создайте суперпользователя с именем пользователя admin.

python manage.py migrate
python manage.py createsuperuser

Логин пользователя

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

В файле tokens/views.py создайте класс LoginView, который аутентифицирует пользователя и создает уникальный токен.

from django.http import JsonResponse
from rest_framework.views import APIView
from rest_framework_simplejwt.tokens import RefeshToken
from django.contrib.auth.models import User
from django.contrib.auth import authenticate


# Create your views here.

class LoginView(APIView):
    def post(self, request):
        username = request.data.get('username')
        password = request.data.get('password')

        user = authenticate(
            username=username, password=password)
        
        refresh = RefeshToken.for_user(user)

        return JsonResponse(
            {
               'refresh':str(refresh),
               'access':str(refresh.access_token) 
            }
        )

В приведенном выше коде мы получаем имя пользователя и пароль из данных запроса, а затем аутентифицируем пользователя с помощью встроенного метода аутентификации.

authenticate() method — это встроенная функция, предоставляемая инфраструктурой аутентификации Django. Он проверяет учетные данные пользователя и аутентифицирует их.

Refresh.for_user(user) — создает токен для пользователя

Наконец, мы возвращаем JsonResponse с обновлением и access_token в виде строк.

Откройте файл root urls.py и сопоставьте LoginView с URL-адресом.

 path('api/login', LoginView.as_view(), name ='login')

Мы будем использовать учетные данные суперпользователя и инструмент POSTMAN для проверки конечной точки входа. Если у вас нет POSTMAN, вы можете найти скачать его здесь.

Откройте Postman и выполните запрос на получение конечной точки http://127.0.0.1:8000/api/login. Тип контента должен быть установлен на application/json.

Как вы можете видеть выше, URL-адрес входа возвращает обновление и токен доступа.

refresh: как следует из названия, токен обновления используется для обновления токенов; Проще говоря, он используется для получения нового токена доступа без входа в систему. Токен обновления имеет более длительный срок действия по сравнению с токеном доступа.

Пользователь может использовать токен обновления, чтобы запросить новый токен доступа, если срок действия токена доступа истек.
Токены обновления имеют более длительный срок действия.

access: для предоставления доступа используется токен доступа. Пользователь будет использовать токен доступа для аутентификации и авторизации запросов приложений. Токены доступа имеют короткий срок действия.

Если мы расшифруем токен доступа, он даст вам следующее

 {
 typ: "JWT",
 alg: "HS256"
}.
{
 token_type: "access",
 exp: 1686203362,
 iat: 1686203062,
 jti: "7ca1b5721c7145feab6b1efe0f127008",
 user_id: 1
}.
[signature]

Заголовок:

  • typ: “JWT” : указывает, что токен является JWT.
  • alg: “HS256” :указывает, что для подписи маркера используется алгоритм HMAC-SHA256.

Полезная нагрузка:

  • token_type: “access”: указывает, что это токен доступа.
  • exp: 1686203362 : указывает отметку времени истечения срока действия токена; метка времени представлена ​​как метка времени Unix.
  • iat: 1686203062 : представляет отметку времени выдачи токена.
  • jti: “7ca1b5721c7145feab6b1efe0f127008” : уникальный идентификатор токена.
  • user_id: 1— идентификатор пользовательского объекта, связанного с токеном. В нашем случае это суперпользователь, а django присвоил id =1
>>> from django.contrib.auth.models import User
>>> user = User.objects.get(username="admin")
>>> user.id
1
>>> 

Подпись:

  • [signature] — указывает подпись JWT,

Давайте создадим защищенное представление и используем токены для авторизации пользователя. Откройте views.py и добавьте следующий код.

from rest_framework.permissions import IsAuthenticated

class RestrictedView(APIView):
    permission_classes = [IsAuthenticated]

    def get(self, request, format=None):
        # Your code here
        return JsonResponse({"response":"YOU ARE ALLOWED HERE"})

Затем сопоставьте представление с URL-адресом.

path('api/restricted', RestrictedView.as_view(), name ='restricted')

Выполните GET-запрос к конечной точке http://127.0.0.1:8000/api/restricted с помощью Postman.

Как видите, он возвращает следующий ответ, так как мы не предоставили токен доступа в заголовке.

{
    "detail": "Authentication credentials were not provided."
}

Добавьте токен доступа в заголовки и снова выполните запрос GET. В параметрах авторизации выберите Bearer Token и добавьте токен доступа в отведенное место.
Как видите, мы получили ожидаемый ответ.

Если вы укажете неправильный или просроченный токен доступа, вы получите эту ошибку:

{
    "detail": "Given token not valid for any token type",
    "code": "token_not_valid",
    "messages": [
        {
            "token_class": "AccessToken",
            "token_type": "access",
            "message": "Token is invalid or expired"
        }
    ]
}

Заключение

В этом руководстве вы познакомились с веб-токенами JSON (JWT), их структурой, их работой за кулисами и тем, как использовать библиотеку Simple JWT в приложении Django. Мы узнали об их значении в процессах аутентификации и авторизации.

Используя JWT с Django Rest Framework, вы можете повысить безопасность своих конечных точек API.

Нажмите здесь, чтобы загрузить бесплатное руководство по Django, которое проведет вас от нуля до полностью работающего приложения Django.

Дополнительные материалы на PlainEnglish.io.

Подпишитесь на нашу бесплатную еженедельную рассылку новостей. Подпишитесь на нас в Twitter, LinkedIn, YouTube и Discord .