Ответ
JWT (JSON Web Token) — это открытый стандарт (RFC 7519) для безопасной передачи информации между сторонами в виде объекта JSON. Информация может быть верифицирована и доверена, поскольку она подписана цифровой подписью.
Структура JWT: Токен состоит из трех частей, разделенных точками:
- Header (Заголовок): Содержит тип токена (JWT) и используемый алгоритм подписи (например, HS256, RS256).
- Payload (Нагрузка): Содержит утверждения (claims) — информацию о сущности (обычно пользователе) и дополнительные данные. Может включать стандартные поля (
iss
,exp
,sub
) и пользовательские. - Signature (Подпись): Создается путем кодирования заголовка и нагрузки в Base64Url, объединения их точкой и подписи полученной строки с использованием секретного ключа и алгоритма из заголовка.
Сценарии использования:
- Аутентификация: После входа пользователя сервер выдает JWT, который клиент затем отправляет с каждым запросом для доступа к защищенным маршрутам.
- Авторизация: В Payload можно включить информацию о ролях и разрешениях пользователя.
- Обмен информацией: Безопасный обмен данными между микросервисами или между клиентом и сервером.
Пример создания и верификации JWT в Python (PyJWT
):
import jwt
from datetime import datetime, timedelta
# Секретный ключ для подписи токена. Должен храниться безопасно!
SECRET_KEY = "your-super-secret-key-that-no-one-knows"
ALGORITHM = "HS256"
# Создание токена
def create_jwt_token(user_id: int, expires_delta: timedelta = None) -> str:
if expires_delta:
expire = datetime.utcnow() + expires_delta
else:
expire = datetime.utcnow() + timedelta(minutes=30) # По умолчанию 30 минут
payload = {
"user_id": user_id,
"exp": expire, # Время истечения токена
"iat": datetime.utcnow() # Время выдачи токена
}
encoded_jwt = jwt.encode(payload, SECRET_KEY, algorithm=ALGORITHM)
return encoded_jwt
# Декодирование и проверка токена
def verify_jwt_token(token: str) -> dict | None:
try:
decoded_payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
return decoded_payload
except jwt.ExpiredSignatureError:
print("Ошибка: Токен истек.")
return None
except jwt.InvalidTokenError:
print("Ошибка: Невалидный токен.")
return None
# Использование
token = create_jwt_token(user_id=123, expires_delta=timedelta(hours=1))
print(f"Созданный токен: {token}")
decoded_data = verify_jwt_token(token)
if decoded_data:
print(f"Декодированные данные: {decoded_data}")
Важные аспекты и лучшие практики:
- Безопасность ключа: Секретный ключ должен быть надежным и храниться в безопасном месте, не в коде.
- HTTPS: Всегда передавайте JWT по защищенному соединению (HTTPS), чтобы предотвратить перехват.
- Время жизни токена (
exp
): Устанавливайте разумное время истечения токена для минимизации рисков при его компрометации. - Алгоритм подписи: Используйте надежные алгоритмы (HS256, RS256) и убедитесь, что сервер проверяет именно тот алгоритм, который ожидается.
- Валидация: Всегда валидируйте все необходимые поля в Payload (например,
exp
,nbf
,iss
,aud
). - Отзыв токенов: JWT по своей природе stateless, что затрудняет их отзыв до истечения срока. Для реализации отзыва часто используются черные списки (blacklists) или короткие сроки жизни токенов с механизмом refresh-токенов.