为什么在会话超时

时间:2018-05-19 18:27:13

标签: ruby-on-rails devise

此处的代码显示,当会话超时(由timeoutable模块检查并强制执

在调用失败应用之前,attempted_pathwarden设置。

问题是:为什么要将重定向设计回当前请求的路径本身?如果会话超时,则不应将客户端重定向到当前实体的登录页面(UserAdmin或其他)?

如果未设置scope_url,它会使用attempted_path。但我不明白为什么要再次重定向到当前请求的路径?这不会导致重定向循环吗?

这个重定向循环实际上发生在Rails管理员身上。如果我为我在Rails管理员身份验证的模型启用timeoutable,那么在会话超时后,任何请求都将导致重定向循环。

有人可以向我解释为什么要重定向到attempted_path吗?用什么用例服务?

其他信息 以下是我想到的两个流程。

应该如何

  • 用户尝试访问第x页。会话超时。
  • 用户被重定向到登录页面
  • 用户登录
  • 用户被重定向回第x页

目前的情况

  • 用户尝试访问第x页。会话超时。
  • 用户被重定向到第x页。

它会重复循环,直到浏览器显示"网站没有正确重定向"。

3 个答案:

答案 0 :(得分:2)

经过长时间的调试周末"我发现问题是因为Session和Cookie中间件放在Warden之后的机架堆栈中。

我的应用程序是一个Rails 5 API应用程序,这意味着默认情况下cookie和会话不可用。尽管是一个API应用程序,我必须出于某些原因合并基于会话/ cookie的身份验证机制。所以我手动将两个中间件添加到机架堆栈中。

由于我在config/application.rb中添加了它们,它们几乎被添加到堆栈的远端,即在Warden中间件本身之后。但是Warden中间件非常清楚它需要在堆栈中使用Session和Cookie管理器before。这样任何会话都会更改它会使最终序列化到会话和cookie中。

这导致失败应用程序被丢弃的会话更改。因此,会话永远不会被清除并导致重定向循环。以下步骤将使其更加清晰。

应该如何

  1. 用户登录。会话设置为用户ID。
  2. 用户使用。会话使用用户ID更新。
  3. 用户空闲(至少在超时期限内)
  4. 用户提出请求。请求与同一会话一起发送。
  5. 会话被识别为超时。清除会话并重定向回同一页面。
  6. 浏览器再次访问同一页面。
  7. 会话中没有用户。重定向到登录页面。
  8. 在我的案例中如何发生

    1. 用户登录。会话设置为用户ID。
    2. 用户使用。会话使用用户ID更新。
    3. 用户空闲(至少在超时期限内)
    4. 用户提出请求。请求与同一会话一起发送。
    5. 会话被识别为超时。
    6. 会话已清除但已清除的会话从未被序列化回cookie。 (这是因为在auth故障控制的情况下直接返回到Warden中间件绕过它所经历的所有中间件。所以它错过了cookie和会话中间件)
    7. 重定向回同一页面。浏览器使会话cookie保持不变。
    8. 浏览器使用相同的会话Cookie再次访问同一页面
    9. 重复步骤5-8,直到浏览器因错误而停止。

      这是一个序列图,我为任何对细节感兴趣的人捕获整个流程。

      Devise Timeout Flow

      @Prometheous:谢谢你的评论。但有一点我还不清楚:

      如果超时,如果FailureApp直接重定向到scope login url,会出现什么问题。你说:

        

      如果没有重定向到尝试的路径,设计就不会知道   如何重定向到登录页面。

      但是,它不能从scope_url部分中使用的else方法获得它:https://github.com/plataformatec/devise/blob/master/lib/devise/failure_app.rb#L128

      scope是肯定的。

      我错过了什么?

答案 1 :(得分:0)

我的猜测是会话超时并要求用户再次登录。

用户尝试访问第x页。

结果是用户会话超时。

用户再次登录。

用户返回第x页。

超时登录会话消息显示在请求的操作中。

答案 2 :(得分:0)

很高兴我能以某种方式帮助你!你做了一个惊人的工作分析整个设计循环过程!

但是,我认为你正在处理一个非常深的嵌套错误,或者设计得不正确。我自己在一个更大的项目上进行了测试,它运行得很好。

在Devise.rb中我取消注释:

config.timeout_in = 10.seconds

并将测试目的更改为10秒。

我在这个项目上有一个FAQ页面,它有一个page_controller。在page_controller里面我添加了:

before_action :authenticate_user!

在我的Devise模型中,在本例中是User,我添加了:

  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable,
         :omniauthable, :timeoutable

当我登录用户时,请转到常见问题解答页面,等待10秒钟,刷新页面,然后重定向到登录页面以及我的会话超时的消息。当我再次登录用户时,我被重定向到FAQ页面,没有任何额外的代码,而不是我上面显示的几个步骤。

流程是(你可能比我理解的要好得多):检查用户是否已登录 - >如果没有,重定向。现在,重定向与:timeoutable模块没有任何关系。 :超时模块'简单地说'倒计时并检查用户会话是否有效,如果没有,那么它会在后台注销用户。如果用户想再次尝试该页面,则使用:authenticate_user!方法,检查用户是否已登录,如果没有,那么,重定向他。

看起来像你的authenticate_user!不按照应有的方式运作。您是否尝试(在开发中)更新设计?

我强烈建议您使用设计创建一个超级简单的应用程序,然后重做上面的步骤,看看它是否按您想要的方式工作。

据我所知,redirect_url部分通常由设计在幕后注入。

我曾经使用config/initializers/devise.rb

为应用程序进行了成本计算

放入Devise.setup |config|

require "custom_path"

config.warden do |manager|
  manager.failure_app = CustomPath
end

,而不是lib/custom_path.rb

class CustomPath < Devise::FailureApp
  def redirect_url
    ## redirect to wherever you want
  end
end

就是这样。然后,Devise将重定向到您想要的任何页面。

无论如何,很高兴您仍然可以通过调整中间件中的某些部分来解决问题。

问候!