Вопрос или проблема
Я разрабатываю веб-приложение на Spring Boot и React, и для аутентификации хочу использовать безсостояние (stateless) с JWT. Однако мне нужны функции, такие как выход пользователя, функция “запомнить меня”, автоматический выход по неактивности, выход из всех устройств, просмотр текущих активных устройств и т.д. Можно ли реализовать все это только с помощью JWT?
Я видел, что люди рекомендуют несколько подходов, включая гибридный подход с использованием краткосрочных JWT-токенов доступа и токенов обновления, которые хранятся в базе данных вместе с идентификатором устройства и его IP-адресом, а также таблицы с черным списком JWT-токенов. Можно также использовать пользовательский jti и хранить его в базе данных для отзыва токенов? Но это не будет полностью безсостоящей архитектурой и будет трудно масштабировать.
Я хотел бы получить опыт и больше узнать о JWT, поэтому использование базовых состояния (stateful) сессий — это мой последний вариант. Пожалуйста, дайте мне знать, какой подход будет наилучшей практикой для реализации?
Я хотел использовать архитектуру без состояния (stateless) с JWT, но некоторые функции трудно реализовать.
Ответ или решение
JWT (JSON Web Token) — это популярный механизм аутентификации, который предоставляет возможность бесшовного взаимодействия с ресурсами без необходимости хранения состояния на сервере. Однако, как вы заметили, реализация некоторых функций, таких как выход пользователя, управление сессиями и отслеживание активных устройств, может быть сложной в полностью безгосударственной архитектуре.
-
Выход пользователя (Logout): Для реализации этой функции вам действительно потребуется сохранить состояние о токенах. Один из распространенных подходов — создание списка черных меток (blacklist) для недействительных токенов. Это может быть реализовано с использованием базы данных, где вы будете сохранять
jti
(JWT ID), сопоставленный с уникальным идентификатором устройства или пользователя. Когда пользователь выполняет выход, вы добавляете соответствующийjti
в черный список, и сервер будет проверять этот список при каждом запросе. Это делает систему менее статeless, но решает проблему выхода пользователя. -
Функция "Запомнить меня" (Remember Me): В этом случае можно использовать сочетание короткоживущих токенов доступа и более долгоживущих токенов обновления (refresh tokens). Токены обновления могут храниться в базе данных и связываться с конкретным устройством, что позволит вам управлять аутентификацией таких пользователей. При активации функции "Запомнить меня" сервер может выдавать более долговременные токены обновления.
-
Тайм-аут неактивности (Idle Timeout): Для управления неактивностью вы можете использовать механизм, который отслеживает временные метки активности пользователя. Если пользователь не отправляет запросы в течение определенного времени, вы можете предложить ему повторно войти в систему, либо просто пометить токен как недействительный, добавив его в черный список.
-
Выход из всех устройств: Для выполнения этой функции вы можете хранить идентификаторы токенов для разных устройств в базе данных. При выходе пользователь из всех устройств вы можете просто удалить записи из базы данных или пометить соответствующие токены как недействительные.
-
Просмотр текущих активных устройств: Вы можете создать таблицу, где будет храниться информация об активных сессиях пользователя, включая идентификаторы токенов, IP-адреса и устройства. При запросе на просмотр активных устройств вы можете извлекать эти данные из базы.
Заключение
Можно настроить архитектуру аутентификации, основанную на JWT, так, чтобы она обеспечивала необходимую функциональность, все же прибегая к некоторому состоянию для управления состоянием сессии пользователя. Это действительно будет являться гибридным решением (смешанная архитектура), и это часто является наилучшим выбором для реализации требований, которые вы описали. Хотя такой подход требует более сложной настройки и может быть не совсем "безгосударственным", он предоставляет большую гибкость и позволяет поддерживать требуемую функциональность, не прибегая к старой, полностью рендернируемой сессии.
Важно понимать, что выбор архитектуры должен основываться на требованиях вашего проекта, сценариях использования и уровне доверия, который вы можете предоставить пользователям. Выбор подхода будет зависеть от вашего конкретного контекста и требований безопасности.