IT-журнал

Django и JWE: Переходим на шифрованные токены для максимальной безопасности

Узнайте, как реализовать авторизацию в Django с использованием JSON Web Encryption (JWE) для защиты данных внутри токенов.

Обновлено 20.09.2026

⏱ 2 мин чтения · 👁 прочитали 4

В современной веб-разработке стандартом де-факто для stateless-авторизации стали JWT (JSON Web Tokens). Однако классический JWT лишь подписывает данные (JWS), оставляя полезную нагрузку (payload) открытой для чтения любым, кто перехватит токен. Если в токене содержатся чувствительные данные — ID пользователя, роли или внутренние идентификаторы — это создает риски безопасности.

Здесь на сцену выходит JWE (JSON Web Encryption). В отличие от JWS, JWE не просто гарантирует целостность данных, но и полностью шифрует содержимое токена.

Почему JWE, а не обычный JWT?

Обычный JWT (точнее, JWS) работает по принципу: «Я подтверждаю, что эти данные не были изменены». Но любой пользователь может вставить строку токена в декодер и увидеть всё содержимое.

Преимущества JWE:
1. Конфиденциальность: Данные внутри токена зашифрованы. Даже если токен будет перехвачен, злоумышленник не узнает, что в нем содержится.
2. Защита от перебора: Скрывая внутреннюю структуру данных, вы усложняете анализ вашего API.
3. Соответствие стандартам: JWE является частью спецификации RFC 7516.

Реализация в Django

Для работы с JWE в экосистеме Python лучше всего подходит библиотека jwcrypto. В отличие от PyJWT, она предоставляет полноценную поддержку шифрования.

1. Установка зависимостей

pip install jwcrypto

2. Создание сервиса для работы с токенами

Рекомендуется вынести логику шифрования в отдельный слой, чтобы не загромождать представления (views).

from jwcrypto import jwk, jwe
import json
from django.conf import settings

class JWEService:
    def __init__(self):
        # В реальном проекте используйте секретный ключ из окружения
        self.key = jwk.JWK.from_text(settings.JWE_SECRET_KEY)

    def encrypt(self, payload: dict) -> str:
        # Создаем объект JWE
        jwetoken = jwe.JWE()
        jwetoken.payload = json.dumps(payload).encode('utf-8')

        # Шифруем с использованием ключа
        jwetoken.encrypt(self.key)
        return jwetoken.serialize(compact=True)

    def decrypt(self, token: str) -> dict:
        try:
            jwetoken = jwe.JWE()
            jwetoken.deserialize(token, compact=True)
            jwetoken.decrypt(self.key)
            return json.loads(jwetoken.payload.decode('utf-8'))
        except Exception as e:
            return None

3. Интеграция в Middleware или Authentication Backend

Чтобы Django понимал JWE-токен при каждом запросе, создадим кастомный класс аутентификации.

from django.contrib.auth.models import User
from rest_framework import authentication, exceptions

class JWEAuthentication(authentication.BaseAuthentication):
    def authenticate(self, request):
        auth_header = request.headers.get('Authorization')
        if not auth_header or not auth_header.startswith('Bearer '):
            return None

        token = auth_header.split(' ')[1]
        service = JWEService()
        payload = service.decrypt(token)

        if not payload:
            raise exceptions.AuthenticationFailed('Invalid or expired token')

        try:
            user = User.objects.get(pk=payload['user_id'])
        except User.DoesNotExist:
            raise exceptions.AuthenticationFailed('User not found')

        return (user, None)

Архитектурные нюансы

Выбор алгоритма

При использовании JWE вы сталкиваетесь с выбором алгоритмов шифрования. Популярный стек:
- Key Management: dir (direct encryption).
- Key Encryption: none (если используется прямой общий ключ).
- Content Encryption: A256GCM (AES-GCM 256 бит) — золотой стандарт по скорости и безопасности.

Срок жизни токена (TTL)

Поскольку JWE шифрует данные, проверка срока действия (exp) происходит только после расшифровки. Обязательно добавляйте временную метку в payload:

import datetime

payload = {
    'user_id': user.id,
    'exp': datetime.datetime.utcnow().timestamp() + 3600
}

Сравнение: JWS vs JWE

Характеристика JWS (Стандартный JWT) JWE
Целостность Да (подпись) Да (шифрование)
Конфиденциальность Нет (base64) Да (шифр)
Размер токена Компактный Больше (из-за метаданных шифра)
Нагрузка на CPU Низкая Средняя

Заключение

Авторизация по JWE в Django — это отличный выбор для систем с повышенными требованиями к безопасности (финтех, медицинские данные, корпоративные CRM). Хотя это добавляет небольшой оверхед к производительности и размеру токена, вы получаете полную гарантию того, что данные пользователя остаются приватными на всем пути от сервера к клиенту и обратно.