#ruby-on-rails #global-variables
#ruby-on-rails #глобальные переменные
Вопрос:
У меня есть приложение только для API, встроенное в Rails, для которого требуется зашифрованный логин для получения токена. Впоследствии запросы на данные из API аутентифицируются с использованием значения токена в заголовке запроса.
У меня есть другое приложение Rails, которое использует этот API для нескольких разных целей. В настоящее время я настроил его на аутентификацию перед выполнением любого запроса, который получает токен для этого запроса.
Это нормально, за исключением того, что оно создает потенциальное условие гонки, как только приложение становится общедоступным. Возможно, что два запроса могут поступать практически одновременно, дважды сбрасывая токен, делая один из последующих запросов на данные us токеном, который больше не действителен.
Я хотел использовать глобальную переменную $ для хранения токена и даты / времени его обновления, чтобы он всегда был доступен для всех пользователей и обновлял токен, только если ему больше пары часов.
Это решило бы проблему состояния гонки, но из всего, что я читаю, ИСПОЛЬЗОВАНИЕ ГЛОБАЛЬНЫХ ПЕРЕМЕННЫХ В RAILS ПЛОХО. Мне кажется, что этот вариант использования является исключением, но я хочу сделать это правильно.
Мой единственный вариант сохранить эти значения в моей собственной базе данных? Кажется глупым настраивать модель данных для таблицы, которая будет содержать только два столбца и две строки, но я не знаю, является ли это Rails Way (TM) или лучшим способом.
Приветствуются любые советы.
Комментарии:
1. Несколько пользователей используют один и тот же токен?
Ответ №1:
Для этого вы можете использовать кеш Rails. Оно сохраняется в памяти или в энергозависимой базе данных, такой как Redis. У вас может быть что-то вроде:
def a_cool_token
Rails.cache.fetch("a_cool_token", expires_in: 2.hours.to_i) do
a_method_to_regenerate_a_cool_token
end
end
Что произойдет, так это:
- При использовании
a_cool_token
для передачи его в запрос он попытается извлечь его из кэша; - В случае, если срок действия этого ключа кэша истек или не определен, он возвращает
a_method_to_regenerate_a_cool_token
; - По истечении установленного времени
expires_in
ключ становится недействительным.
Вы всегда можете использовать более полный ключ кэша, используя для его создания некоторый запрос к базе данных, например:
Rails.cache.fetch("a_cool_token/#{some_timestamp_that_gets_updated_with_a_cool_token}", expires_in: 2.hours.to_i)
Реализация def some_timestamp_that_gets_updated_with_a_cool_token
может извлекаться при последнем обновлении токена, избегая устаревших ответов, если что-то еще изменяет токен снаружи a_cool_token
Я надеюсь, что это поможет указать вам на «хорошее» решение.
Комментарии:
1. Неплохо. Из любопытства, это
to_i
нужно2.hours
?2.
expires_in
должно быть целое число секунд 🙂3. Итак, я делал, например,
expires in 10.minutes
(нетto_i
). И, похоже, это работает. Но это неверно?4. Мне нравится это решение. Спасибо за помощь!
5. @jvillian это зависит от библиотеки, которая взаимодействует с базой данных, некоторые не поддерживают нецелые значения.