Удалить JWT при выходе из приложения Spring
Мы пытаемся следовать этой кодовой базе для нашего приложения на основе Spring REST. пружинно-загрузочные-jwts
Проблема в том, что мы не можем удалить токен JWT во время выхода с сервера. Когда мы проверили в сети, мы узнали, что единственный подход к этому - это внесение в черный список токенов JWT, как указано в этом черном списке. Это так?
Мы немного новичок в аутентификации на основе токенов. Пожалуйста, дайте нам знать, есть ли решение, такое как истечение срока действия токена при вызовах выхода из системы или что-то в этом роде.
3 ответа
Длинная история short
необходимо создать механизм для удаления или аннулирования токена manually
на выходе.
Должен ли я хранить токен JWT или нет?
Вопрос, который вы должны задать себе:
- Нужно ли хранить токен JWT в базе данных? Если так, то почему?
Приведенный выше вопрос не обязательно решит ваш logout
проблема, потому что вам все еще нужен механизм для invalidate
токен, который хранится или не хранится в database
,
Одно из преимуществ not storing
маркер в базе данных заключается в том, что вам не нужно беспокоиться о deleting
их когда (без обслуживания или некоторого процесса очистки)
- Они токен истекает
- Изменяются их области применения
- Пользователь (в случае
password
поток, давайте не будем покрывать другиеflows
) роли и разрешения понижены или обновлены в базе данных и, следовательно, что внутри jwt устарело - Пользователь удален
- Пользователь вышел из системы (интересно, если это достаточно веская причина для удаления токена)
- Жетоны скомпрометированы (хитрый)
- [Добавить другие случаи]
Проверка правильности токена?
Я уверен, что вы используете verify
конечная точка, и ее цель состоит в том, чтобы проверить, является ли токен valid
или нет, но не обязательно проверять все вышеописанные сценарии, что означает, что вы должны либо
- Настроить
verify
рабочий процесс, чтобы добавить большеcustom checks
ИЛИ ЖЕ - До того, как токен
verified
заsignature validity
,expiry time
и некоторые другиеdefault checks
вы можете запустить свой собственныйcustom checks
и если вашcustom checks
прошло, то действуй иначеyou shall not pass!
Каковы ваши варианты тогда?
Ну кроме того blacklisting
Вы могли бы сделать что-то, как следует
Используйте хранилище в памяти
Просто сохраните uniquely-identifying-metadata
токена JWT в Redis в качестве ключа и дать ему expiry time
это так же, как JWT
время истечения токена, чтобы оно self-destruct
когда токен истек.
set key {replace_with_jwt_unique_identifier} ex {jwt_expiry_timestamp}
Риск: Redis хранится в памяти, и записи не сохраняются.
Использовать базу данных
Не используйте Redis или не хотите рисковать. Вы можете использовать базу данных с пользовательской таблицей базы данных. Отдельная таблица, которая либо
- Связанный с записью JWT и имеет
ON DELETE CASCADE
- Не связано с записью JWT, и вы должны вести ее самостоятельно
При выдаче токена также заполните эту новую таблицу базы данных.
Общие оставшиеся шаги
Когда normal
запрос приходит с JWT, используйте JWT для запроса in-memory
магазин или database
таблица, чтобы увидеть, если запись существует. В случае in-memory
хранить простой existence
чек более чем достаточно. В случае database table
вам нужно сделать больше проверок (т.е. существуют и не просрочены и т. д.), и если проверки прошли, пропустите запрос, иначе you shall not pass!
Когда logout request
приходит, в случае in-memory
магазин просто удалите key
и продолжить (если найден) и в случае database
Вы можете удалить JWT
запись, которая будет каскадно спускаться к новой таблице.
Когда делать пользовательские проверки?
Ну, вы можете сделать это
- Прежде всего, используя пользовательский фильтр верхнего уровня или
- Вы можете расширить
verify
рабочий процесс конечной точки, чтобы также сделать эти дополнительные проверки
Проекты, с которыми я работаю, не требуют, чтобы токен был признан недействительным logout
поэтому мне не пришлось пересекать этот мост. Я должен был расширить verify
конечная точка, чтобы убедиться, что токен действителен, если все мои custom checks
Прошло.
Дополнительные материалы для чтения
В дополнение к учебнику, который вы указали. Есть некоторые другие вопросы SO, которые также обсуждают аналогичную проблему. Увидеть
Что делать, если JWT украден?
Как уничтожить JWT при выходе?
Подробнее как удалить токен JWT?
Как включить JWT при смене пароля
Github проблема - как сделать недействительным JWT
И, наконец, лучшее для последнего - аннулирование веб-токенов JWT
Мы столкнулись с подобной проблемой и решили ее следующим способом:
- Мы добавляем идентификатор запроса к каждому токену JWT вместе со сроком действия.
- Когда сеанс создан, мы сохраняем этот идентификатор запроса в базе данных против других значений токена и его срока действия.
- Когда сервер инициирует выход из системы, мы помечаем этот запрос как просроченный.
- В следующий раз, если используется тот же токен, мы точно знаем, что это токен с истекшим сроком действия, проверив идентификатор запроса.
Теперь проверка идентификатора запроса в базе данных является дорогостоящей, поэтому мы также используем кэш в памяти.
Преимущество токена JWT заключается в том, что он обеспечивает автономный способ безопасной передачи информации между сторонами в виде объекта JSON. Эта информация может быть проверена и надежна, потому что она имеет цифровую подпись.
Поскольку он является автономным, любой ваш ресурсный сервер сможет проверить его без необходимости поиска в БД или доступа к серверу авторизации.
Теперь, если ваше требование состоит в том, чтобы сделать токен недействительным, я предлагаю изучить хранилище JDBC TokenStore, которое предлагает Spring-Security. Таким образом, все выданные токены будут храниться в БД, и вы можете сделать их недействительными, когда пользователь выйдет из вашего приложения. Для этого вы можете предоставить сервис для отзыва токена и соответствующего вызова
@Resource(name="tokenServices")
ConsumerTokenServices tokenServices;
@RequestMapping(method = RequestMethod.POST, value = "/tokens/revoke/{tokenId:.*}")
@ResponseBody
public String revokeToken(@PathVariable String tokenId) {
tokenServices.revokeToken(tokenId);
return tokenId;
}
Все ваши серверы ресурсов должны будут выполнить поиск в БД, чтобы проверить правильность токена