← Назад к вопросам

Хранил ли токен на стороне сервера

2.2 Middle🔥 112 комментариев
#Процессы и методологии разработки#Теория тестирования

Комментарии (2)

🐱
deepseek-v3.2PrepBro AI6 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Серверное хранение токенов: архитектурные решения и практики

Да, хранение токенов на стороне сервера является распространённой и часто необходимой практикой в современных веб-приложениях, особенно когда речь идет о сессионных токенах или refresh-токенах в архитектуре OAuth 2.0. Однако важно понимать контекст, типы токенов и соответствующие паттерны безопасности.

Основные сценарии серверного хранения

Серверное хранение оправдано в нескольких ключевых сценариях:

  1. Хранение сессионных идентификаторов (Session IDs): Это классическая модель. После успешной аутентификации сервер создаёт запись сессии (часто в базе данных или in-memory хранилище типа Redis) и отправляет клиенту только ID этой сессии (обычно в cookie). Весь контекст пользователя (роли, права, данные) хранится на сервере.

    // Пример: создание сессии в Node.js с использованием express-session
    const session = require('express-session');
    const RedisStore = require('connect-redis')(session);
    
    app.use(session({
        store: new RedisStore({ client: redisClient }),
        secret: 'your-secret-key',
        resave: false,
        saveUninitialized: false,
        cookie: { secure: true, httpOnly: true, maxAge: 24 * 60 * 60 * 1000 } // 1 день
    }));
    
  2. Хранение хешированных refresh-токенов: В JWT-подходе access-токен (короткоживущий, содержащий claims) клиент хранит самостоятельно. Но долгоживущий refresh-токен, используемый для получения новых access-токенов, должен храниться на сервере в безопасном виде (хешированным, аналогично паролям). Это позволяет реализовать механизм отзыва (revoke) токенов.

    -- Пример структуры таблицы для хранения refresh-токенов
    CREATE TABLE user_refresh_tokens (
        id SERIAL PRIMARY KEY,
        user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
        token_hash VARCHAR(255) NOT NULL, -- Хеш самого токена
        expires_at TIMESTAMP NOT NULL,
        created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
        revoked BOOLEAN DEFAULT FALSE
    );
    -- При попытке обновления access-токена сервер проверяет наличие и валидность хеша refresh-токена в этой таблице.
    
  3. Чёрные списки (blocklist/denylist) токенов: Даже для stateless JWT access-токенов иногда требуется механизм принудительного разлогинивания до истечения срока их действия. Для этого сервер может хранить идентификаторы отозванных (но ещё не истёкших) токенов в быстром хранилище типа Redis.

    # Пример добавления токена в blocklist в Python (Flask)
    import redis
    from datetime import datetime, timedelta
    
    redis_client = redis.Redis(host='localhost', port=6379, db=0)
    
    def revoke_token(jti, expires_in_seconds):
        """Добавляет идентификатор токена (jti) в Redis с TTL, равным оставшемуся сроку жизни токена."""
        redis_client.setex(f"token_blocklist:{jti}", expires_in_seconds, "revoked")
    
    # В middleware проверки токена:
    def verify_token(jwt_payload):
        jti = jwt_payload['jti']
        if redis_client.exists(f"token_blocklist:{jti}"):
            raise Exception('Token has been revoked')
    

Преимущества и недостатки

Преимущества серверного хранения:

  • Контроль и безопасность: Сервер может в любой момент отозвать сессию или refresh-токен, обеспечивая безопасность при компрометации.
  • Богатый контекст: В сессии можно хранить больше данных, не увеличивая размер передаваемого клиенту токена.
  • Соответствие требованиям: Некоторые стандарты безопасности (например, для финансовых приложений) могут явно требовать серверного контроля над сеансами.

Недостатки и риски:

  • Нагрузка на хранилище: Требует масштабируемого и отказоустойчивого хранилища (Redis, БД).
  • Сложность в микросервисной архитектуре: Stateful-сессии усложняют балансировку нагрузки и создают точку отказа. Stateless JWT (без сессий) часто предпочтительнее для межсервисного взаимодействия.
  • Риски при неправильной реализации: Уязвимости (например, фиксация сессии, недостаточно сильные идентификаторы сессии) могут свести на нет все преимущества.

Рекомендации по безопасности

При хранении токенов на сервере критически важно следовать практикам:

  • Для сессионных идентификаторов используйте криптографически стойкие генераторы.
  • Устанавливайте для сессионных cookies атрибуты HttpOnly (защита от XSS), Secure (только HTTPS) и SameSite.
  • Реализуйте регулярную очистку просроченных и неактивных сессий из хранилища.
  • Для refresh-токенов всегда храните только их криптографический хеш (например, с помощью bcrypt или Argon2).
  • Обеспечьте надёжную защиту самого серверного хранилища (например, настройки безопасности Redis).

Вывод: Хранение токенов на стороне сервера — не устаревший, а вполне актуальный подход, выбор которого зависит от архитектурных требований (механизмы отзыва, хранение состояния пользователя, комплаенс). Ключевое решение — это не «хранить или не хранить», а что именно хранить (идентификатор сессии, хеш refresh-токена) и как это делать безопасно, комбинируя серверные и клиентские механизмы для создания надёжной системы аутентификации и авторизации.

Хранил ли токен на стороне сервера | PrepBro