Где хранить токен аутентификации в RESTful API

Я начал разрабатывать RESTful API, и я думаю о том, как обрабатывать аутентификацию. Я хочу использовать какой-то токен аутентификации, но я не могу использовать OAuth o аналогичных инфраструктур, поэтому я должен сам справиться с этим.

Одним из требований к этому API является то, что он должен иметь хорошую производительность, достаточную для обработки большого объема запросов до того, как потребуется масштабирование; моя забота заключается в том, как сделать по каждому запросу время, необходимое для проверки токена (целостность, срок действия, IP-адрес и т.д.), насколько это возможно.

Я предполагаю, что токен должен иметь какой-то хэш, а не зашифрованную строку, содержащую пользовательскую информацию, потому что время дешифрования будет тяжелым.

Я читал, что я могу хранить токены в хэш-таблице в памяти, где ключ является токеном, а значение - это информация пользователя, необходимая для обработки запроса, но как я могу сделать эту работу в кластерной среде, где будет хеш-таблица на каждом "node"?

Должен ли я помещать токены в таблицу БД каждый раз ударять БД и вручную обрабатывать сохранение просроченных билетов?

Возможно, это не так важно для вопроса, но я использую Spring MVC для RESTfull API.

Спасибо заранее.

Ответ 1

Я решил свою проблему, используя как кеш в памяти, так и кеш db. Вот краткое изложение моего решения, которое может помочь любому с той же задачей.

  • пользователь входит в систему и в этот момент генерируется уникальный уникальный ключ и отправляется обратно пользователю.
  • этот токен входа (который в основном является GUID с некоторой обработкой) также хранится в таблице db с дополнительной информацией, такой как exipiration и с информацией пользователя и ролями. те же фрагменты информации также хранятся в памяти (хэш-таблица google guava, где токен является ключом)
  • токен должен быть передан вместе с каждым вызовом api в токена авторизации, поскольку @ipa предложил
  • код сервера проверяет, находится ли токен в кеше памяти, информация пользователя уже доступна (например, вызов api выполняется на другом node в кластере), токен - это поиск в токене db
  • После обнаружения токена вы можете проверить истечение срока действия, роли и т.д.

Это обеспечивает хороший уровень производительности и безопасности, токен может быть сгенерирован любым произвольным алгоритмом даже относительно медленным, поскольку вам не нужно пересчитывать его при каждом вызове api. Также это работает с услугой без гражданства, которую можно масштабировать горизонтально.

Ответ 2

Я предполагаю, что вы используете https, и поэтому весь трафик зашифрован. Я бы предложил один из следующих принципов.

Основная проверка подлинности

Вы можете добавить учетные данные в заголовок авторизации запроса. Эти учетные данные закодированы Base64 (см. Ниже). Эти учетные данные могут быть отправлены по каждому запросу, а затем проверены с помощью вашей БД. Чтобы ускорить работу и уменьшить интенсивность ввода-вывода, вы все равно можете использовать кеш. Как только я реализовал API, подобный этому без кеша, и смог обрабатывать тысячи запросов в секунду.

Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==

Ток авторизации

Существуют различные способы реализации вашей идеи с помощью токена. Общим является то, что каждый пользователь API имеет свой собственный токен, обычно называемый ключом api, который никогда не истекает. Еще один из них заключается в том, что вам сначала нужно авторизовать (базовая аутентификация), а затем получить токен, срок действия которого истекает. Затем он используется как ключ api в течение определенного времени.

В любом случае вам нужно решить, использовать кеш или нет. Я бы сохранил это просто и пошел на базовую аутентификацию и каждый раз проверял db. Практически каждая структура имеет очень хорошую поддержку для этого подхода, потому что это простой http. Если это вызывает проблемы с производительностью (я бы рекомендовал тесты производительности), попробуйте добавить таблицу с вашими учетными данными в кэш JPA. Если вы хотите что-то реализовать с истекающими токенами, взгляните на Infinispan.

Ответ 3

Вы можете хранить токен в Redis. Если вы собираетесь хранить его в БД, убедитесь, что вы оптимизировали сервер (если вы его управляете) для операций чтения. У меня есть пара реализации, в которой люди также использовали хранилище значений ключей. Hashtable - тоже хорошая идея.