Ответ
Процесс аутентификации с использованием JSON Web Token (JWT) — это stateless-механизм, который позволяет серверу проверять подлинность запросов без хранения сессионных данных.
Алгоритм взаимодействия:
- Аутентификация: Клиент отправляет свои учетные данные (например, логин и пароль) на специальный эндпоинт сервера (например,
/login). - Генерация и выдача токена: Сервер проверяет учетные данные. В случае успеха он создает JWT, который содержит полезную нагрузку (
payload) с информацией о пользователе (например,user_id) и метаданными (например, срок действия токенаexp). Токен подписывается секретным ключом, известным только серверу. - Хранение токена: Сервер отправляет сгенерированный JWT клиенту. Клиент должен сохранить его (например, в
localStorage,sessionStorageилиHttpOnlycookie). - Авторизация запросов: При каждом последующем запросе к защищенным ресурсам клиент должен включать JWT в заголовок
Authorizationсо схемойBearer.Authorization: Bearer <your_jwt_token> - Верификация на сервере: Сервер получает токен из заголовка, проверяет его подпись с помощью своего секретного ключа и валидность (например, не истек ли срок действия). Если все проверки пройдены, сервер обрабатывает запрос.
Пример на Python с PyJWT:
import jwt
import datetime
from functools import wraps
from flask import Flask, request, jsonify
app = Flask(__name__)
app.config['SECRET_KEY'] = 'your-super-secret-key'
# --- Генерация токена при логине ---
@app.route('/login', methods=['POST'])
def login():
# Здесь должна быть реальная проверка пользователя
# ...
# Создаем токен со сроком жизни 30 минут
token = jwt.encode({
'user_id': 123,
'exp': datetime.datetime.utcnow() + datetime.timedelta(minutes=30)
}, app.config['SECRET_KEY'], algorithm="HS256")
return jsonify({'token': token})
# --- Декоратор для защиты эндпоинтов ---
def token_required(f):
@wraps(f)
def decorated(*args, **kwargs):
token = None
if 'Authorization' in request.headers:
token = request.headers['Authorization'].split(" ")[1]
if not token:
return jsonify({'message': 'Токен отсутствует!'}), 401
try:
data = jwt.decode(token, app.config['SECRET_KEY'], algorithms=["HS256"])
current_user_id = data['user_id']
except jwt.ExpiredSignatureError:
return jsonify({'message': 'Срок действия токена истек!'}), 401
except jwt.InvalidTokenError:
return jsonify({'message': 'Невалидный токен!'}), 401
return f(current_user_id, *args, **kwargs)
return decorated
# --- Защищенный эндпоинт ---
@app.route('/protected')
@token_required
def protected_route(current_user_id):
return jsonify({'message': f'Доступ разрешен для пользователя {current_user_id}'})