我有一个使用Devise进行身份验证的应用。登录字段位于主页上。如果我打开两个选项卡(选项卡A和选项卡B,然后手动注销每个选项卡(第一个选项卡A,然后选项卡B),然后返回选项卡A并尝试登录,我收到InvalidAuthenticityToken错误。
然后我可以回到标签B并尝试登录并获取错误。然后返回选项卡A并尝试登录并再次获取错误。这将无限期地发生,直到您在同一选项卡中收到InvalidAuthenticityToken错误后立即尝试登录选项卡。
我可以在ApplicationController中设置以下内容:
protect_from_forgery :with => :null_session
但是现在第一次登录尝试将返回主页,但没有指出您的登录失败的原因(您只是再次看到主页而不是InvalidAuthenticityToken错误页面)。如果您再次尝试登录(在同一选项卡上),则会成功。
我知道为什么会发生这种情况:会话正在重置注销,这会重置会话中的csrf_token
。第二个选项卡重置该标记,但第一个选项卡仍然具有前一个标记。因此,当第一个标签提交表单时,csrf_token
无效。
我可以在服务器端执行此操作吗?或者我将不得不做一些疯狂的解决方法,比如在你注销时在localStorage中设置一些东西,或者打开一个websocket,这样我就会在主页上通知另一个选项卡重置了CSRF令牌?
让一个打开多个标签的用户看起来似乎很少见并手动注销,但这只是模拟网站的实际行为:10分钟后自动将其记录下来。这实际上经常在我们的应用程序中发生。
答案 0 :(得分:0)
Rails允许您使用rescue_from
通过回调函数来挽救您选择的错误。
您可以在此处找到更多信息: https://api.rubyonrails.org/classes/ActiveSupport/Rescuable/ClassMethods.html
解决了几乎相同的问题,我的Sessions控制器顶部看起来像这样
class SessionsController < ApplicationController
rescue_from ::ActionController::InvalidAuthenticityToken, with: :redirect_home
和我在同一控制器中定义的回调类似
def redirect_home
redirect_to root_url
end