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"Ласкаво просимо, {payload['username']}!"}
    except Exception as e:
        return {"error": str(e)}

Практичне застосування

На практиці JWT використовують для:

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

Однак пам'ятайте: безпека понад усе! Тримайте секретні ключі в секреті і використовуйте короткі строки дії токенів.

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


3
Опитування
Типи токенів у OAuth2: Access і Refresh Tokens, рівень 4, лекція 4
Недоступний
Типи токенів у OAuth2: Access і Refresh Tokens
Типи токенів у OAuth2: Access і Refresh Tokens
Коментарі
ЩОБ ПОДИВИТИСЯ ВСІ КОМЕНТАРІ АБО ЗАЛИШИТИ КОМЕНТАР,
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ