JavaRush /Курсы /Модуль 4: FastAPI /Генерация и проверка JWT-токенов

Генерация и проверка JWT-токенов

Модуль 4: FastAPI
4 уровень , 4 лекция
Открыта

JWT — это JSON Web Token, компактный и безопасный способ передачи информации между двумя сторонами в виде токена. Здесь ключевое слово — компактный. JWT — это всего лишь строка, которая содержит информацию (payload), закодированную в формате JSON, с подписью для верификации.


Структура JWT

JWT состоит из трёх частей, разделённых точками:

  1. Header (заголовок) — информация о типе токена (JWT) и алгоритме подписи, например, HMAC или RSA.
  2. Payload (полезная нагрузка) — собственно данные, которые вы передаёте: например, идентификатор пользователя, роль, срок действия токена.
  3. Signature (подпись) — цифровая подпись, используемая для проверки целостности данных.

Пример JWT:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoxLCJyb2xlIjoiYWRtaW4iLCJleHBpcnkiOjE2NzI4MTU2MDB9.2bc89a2c5e2c0f3bea865d3c8b4d9e3c8123e5f5

Расшифровав это, мы получим:

  1. Header (base64):
    {
        "alg": "HS256",
        "typ": "JWT"
    }
  2. Payload (base64):
    {
        "user_id": 1,
        "role": "admin",
        "expiry": 1672815600
    }
  3. Signature (hex):
    2bc89a2c5e2c0f3bea865d3c8b4d9e3c8123e5f5

Эта структура позволяет вам безопасно передавать данные и проверять их подлинность на стороне сервера.


Почему JWT?

Вы, наверное, задаетесь вопросом: "Почему именно JWT? Почему не сессии или другие формы токенов?" Вот несколько причин:

  1. JWT самодостаточен: он содержит всю информацию о пользователе, не требуя обращения к базе данных.
  2. Он легко масштабируется: вы можете использовать его в распределённых архитектурах.
  3. JWT работает вне коробки с большинством современных технологий.
  4. Токен подписан, что предотвращает его подделку (если используется хороший секретный ключ).

Генерация JWT в FastAPI

FastAPI — это удивительная штука, и благодаря библиотеке PyJWT работа с JWT становится ещё проще.

Установка библиотеки

Для работы с JWT установим библиотеку PyJWT:

pip install pyjwt

Теперь создадим код для генерации токенов.

Генерация токенов

Вот пример функции для создания JWT с использованием алгоритма HMAC SHA256:


from datetime import datetime, timedelta
from typing import Union
import jwt

# Секретный ключ для подписи токенов (держите его в секрете!)
SECRET_KEY = "super_secret_key_please_change_me"
ALGORITHM = "HS256"

def create_access_token(data: dict, expires_delta: Union[timedelta, None] = None):
    """
    Создаёт JWT токен.

    :param data: Полезная нагрузка токена (например, идентификатор пользователя).
    :param expires_delta: Время жизни токена (опционально).
    :return: Строка JWT.
    """
    to_encode = data.copy()
    
    if expires_delta:
        expire = datetime.utcnow() + expires_delta
    else:
        expire = datetime.utcnow() + timedelta(minutes=15)  # токен живёт 15 минут по умолчанию
    to_encode.update({"exp": expire})
    
    encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
    return encoded_jwt

Как это работает?

  • Мы добавляем поле exp для указания срока действия токена.
  • Полезная нагрузка (data) дополняется информацией о сроке действия.
  • Затем мы подписываем токен с использованием секретного ключа.

Пример использования функции:


payload = {"user_id": 1, "role": "admin"}
access_token = create_access_token(data=payload, expires_delta=timedelta(hours=1))
print(access_token)

Вы получите строку вида:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoxLCJyb2xlIjoiYWRtaW4iLCJleHBpciI6MTY3MjgxNjAwMH0.T1wGbYFvEc2nOdfAqJ5CkpA0u2V2_q2BdV0Ysx8n3VU

Проверка и декодирование JWT

После того как ваш сервер сгенерировал JWT, нужно уметь его проверять.

Проверка токенов с PyJWT

Для проверки токенов используется функция jwt.decode. Вот пример:


def verify_token(token: str):
    """
    Проверяет подлинность токена и возвращает полезную нагрузку.

    :param token: JWT токен.
    :return: Декодированные данные токена.
    """
    try:
        payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
        return payload
    except jwt.ExpiredSignatureError:
        raise Exception("Токен истёк!")  # Обработка ошибки истечения срока действия
    except jwt.InvalidTokenError:
        raise Exception("Недействительный токен!")  # Обработка других ошибок

Как это работает?

  • jwt.decode() проверяет подпись токена.
  • Если токен истёк, выбрасывается исключение ExpiredSignatureError.
  • Для недействительных токенов выбрасывается InvalidTokenError.

Пример использования:


token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoxLCJyb2xlIjoiYWRtaW4iLCJleHBpciI6MTY3MjgxNjAwMH0.T1wGbYFvEc2nOdfAqJ5CkpA0u2V2_q2BdV0Ysx8n3VU"
try:
    payload = verify_token(token)
    print(payload)
except Exception as e:
    print(str(e))

Если всё нормально, вы увидите полезную нагрузку:

{'user_id': 1, 'role': 'admin', 'exp': 1672816000}

Интеграция в FastAPI

Теперь объединим всё это в FastAPI-приложении.

Пример эндпоинта для создания токена


from fastapi import FastAPI, Depends
from pydantic import BaseModel

app = FastAPI()

class TokenData(BaseModel):
    username: str

@app.post("/token")
async def generate_token(data: TokenData):
    """
    Создаёт JWT токен для пользователя.
    """
    payload = {"username": data.username}
    access_token = create_access_token(data=payload)
    return {"access_token": access_token, "token_type": "bearer"}

Пример эндпоинта для проверки токена


from fastapi.security import OAuth2PasswordBearer

oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")

@app.get("/protected")
async def protected_route(token: str = Depends(oauth2_scheme)):
    """
    Пример защищённого маршрута.
    """
    try:
        payload = verify_token(token)
        return {"message": f"Welcome, {payload['username']}!"}
    except Exception as e:
        return {"error": str(e)}

Практическое применение

На практике JWT используются для:

  1. Защиты эндпоинтов: только пользователи с валидными токенами могут получить доступ.
  2. Подтверждения подлинности: токен содержит информацию только для одного пользователя.
  3. Микросервисов: JWT позволяет передавать данные между сервисами.

Однако помните: безопасность прежде всего! Держите секретные ключи в секрете и используйте короткие сроки действия токенов.

Официальная документация PyJWT: https://pyjwt.readthedocs.io/


1
Задача
Модуль 4: FastAPI, 4 уровень, 4 лекция
Недоступна
Создание JWT токена
Создание JWT токена
1
Задача
Модуль 4: FastAPI, 4 уровень, 4 лекция
Недоступна
Проверка JWT токена
Проверка JWT токена
3
Опрос
Типы токенов в OAuth2: Access и Refresh Tokens, 4 уровень, 4 лекция
Недоступен
Типы токенов в OAuth2: Access и Refresh Tokens
Типы токенов в OAuth2: Access и Refresh Tokens
Комментарии
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ