我在Rails中内置了一个仅限API的应用程序,它需要加密登录才能接收令牌。随后,来自 API 的数据请求将使用请求标头中的令牌值进行身份验证。
我有另一个Rails应用程序,它使用此API进行一些不同的事情。目前,我已将其设置为在发出任何请求之前进行身份验证,从而获取该请求的令牌。
这很好,除了一旦应用程序可供公众使用,它就会设置潜在的争用条件。两个请求可能几乎同时出现,重置令牌两次,使其中一个后续数据请求成为不再有效的令牌。
我想使用 $global 变量来存储令牌及其刷新日期/时间,以便所有用户始终可以使用它,并且仅在令牌超过几个小时时刷新令牌。
这将解决竞争条件问题,但从我正在阅读的所有内容来看,在 RAILS 中使用全局变量是不好的。在我看来,这个用例是一个例外,但我想以正确的方式做到这一点。
我的唯一选择是将这些值存储在我自己的数据库中吗?为一个只包含两列两行的表设置数据模型似乎很愚蠢,但我不知道这是 Rails Way(TM) 还是最佳方法。
任何建议不胜感激。
你可以使用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
我希望这有助于为您指出一个"好"的解决方案。