Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Что такое JWT?
JWT (JSON Web Token) — это подписанный токен для безопасной передачи информации между клиентом и сервером. Структура JWT: Header.Payload.Signature
- Header (Base64) — алгоритм подписи (HS256, RS256)
- Payload (Base64) — данные пользователя (sub, name, exp)
- Signature (HMAC/RSA) — криптографическая подпись
Почему JWT безопасен?
1. Криптографическая подпись предотвращает подделку
JWT подписывается с использованием секретного ключа. Изменение любого бита в Header или Payload автоматически инвалидирует подпись:
import jwt
from datetime import datetime, timedelta
SECRET_KEY = 'super-secret-key'
# Создание токена
payload = {
'sub': '502',
'name': 'Alice',
'exp': datetime.utcnow() + timedelta(hours=1)
}
token = jwt.encode(payload, SECRET_KEY, algorithm='HS256')
# Проверка подписи
decoded = jwt.decode(token, SECRET_KEY, algorithms=['HS256'])
# Попытка подделки: изменить name
forged_token = token[:-10] + 'XXXXXXXXXX'
try:
jwt.decode(forged_token, SECRET_KEY, algorithms=['HS256'])
except jwt.InvalidSignatureError:
print('Подпись недействительна!')
2. Невозможно подделать без секретного ключа
Хакер видит только Base64-encoded данные. Он может декодировать Header и Payload, но не может создать правильную подпись без SECRET_KEY.
3. Проверка осуществляется на сервере
Сервер имеет SECRET_KEY и может мгновенно проверить подлинность токена:
from fastapi import FastAPI, Depends, HTTPException
from fastapi.security import HTTPBearer
import jwt
app = FastAPI()
security = HTTPBearer()
SECRET_KEY = 'super-secret-key'
async def verify_token(credentials = Depends(security)):
token = credentials.credentials
try:
payload = jwt.decode(token, SECRET_KEY, algorithms=['HS256'])
user_id = payload.get('sub')
return user_id
except jwt.InvalidSignatureError:
raise HTTPException(status_code=401, detail='Invalid token')
except jwt.ExpiredSignatureError:
raise HTTPException(status_code=401, detail='Token expired')
@app.get('/protected')
async def protected_route(user_id: str = Depends(verify_token)):
return {'message': f'Hello, user {user_id}'}
4. Защита от обычных атак
Man-in-the-Middle (MITM): JWT должен передаваться по HTTPS, чтобы хакер не мог перехватить и переиспользовать токен.
Cross-Site Request Forgery (CSRF): JWT хранится в httpOnly cookie или заголовке Authorization. Это предотвращает доступ из JavaScript.
# Правильно: httpOnly cookie
response.set_cookie(
'token',
token,
httponly=True,
secure=True,
samesite='Strict'
)
Асимметричная криптография (RS256)
Для более высокой безопасности используется RSA вместо HMAC:
import jwt
from cryptography.hazmat.primitives.asymmetric import rsa
# Генерация пары ключей
private_key = rsa.generate_private_key(public_exponent=65537, key_size=2048)
public_key = private_key.public_key()
# Подпись с приватным ключом (только сервер)
payload = {'sub': '502', 'name': 'Alice'}
token = jwt.encode(payload, private_key, algorithm='RS256')
# Проверка с публичным ключом
decoded = jwt.decode(token, public_key, algorithms=['RS256'])
Потенциальные уязвимости JWT
Слабый SECRET_KEY
# Плохо
SECRET_KEY = '123456'
# Хорошо
import secrets
SECRET_KEY = secrets.token_urlsafe(32)
Отсутствие TTL
# Плохо: токен без срока действия
payload = {'sub': '502'}
# Хорошо: добавить exp
from datetime import datetime, timedelta
payload = {
'sub': '502',
'exp': datetime.utcnow() + timedelta(hours=1)
}
Хранение чувствительных данных
# Плохо
payload = {'user_id': 502, 'password': 'secret123'}
# Хорошо
payload = {'sub': '502', 'roles': ['user', 'admin']}
Забыть о Blacklist при logout
def logout(token: str):
# Добавить токен в blacklist с TTL = оставшемуся времени
r.setex(f'blacklist:{token}', 3600, '1')
Вывод
JWT безопасен по конструкции благодаря:
- Криптографической подписи — подделка очень сложна
- Невозможности подделать без секретного ключа
- Быстрой проверке на сервере
- Защите от типичных веб-атак (CSRF, session fixation)
Но нужно помнить:
- Используй HTTPS
- Установи разумный TTL
- Используй сильный SECRET_KEY
- Не храни чувствительные данные в payload
- Реализуй blacklist при logout