此处的代码显示,当会话超时(由timeoutable
模块检查并强制执
在调用失败应用之前,attempted_path
由warden
设置。
问题是:为什么要将重定向设计回当前请求的路径本身?如果会话超时,则不应将客户端重定向到当前实体的登录页面(User
或Admin
或其他)?
如果未设置scope_url
,它会使用attempted_path
。但我不明白为什么要再次重定向到当前请求的路径?这不会导致重定向循环吗?
这个重定向循环实际上发生在Rails管理员身上。如果我为我在Rails管理员身份验证的模型启用timeoutable
,那么在会话超时后,任何请求都将导致重定向循环。
有人可以向我解释为什么要重定向到attempted_path
吗?用什么用例服务?
其他信息 以下是我想到的两个流程。
它会重复循环,直到浏览器显示"网站没有正确重定向"。
答案 0 :(得分:2)
经过长时间的调试周末"我发现问题是因为Session和Cookie中间件放在Warden之后的机架堆栈中。
我的应用程序是一个Rails 5 API应用程序,这意味着默认情况下cookie和会话不可用。尽管是一个API应用程序,我必须出于某些原因合并基于会话/ cookie的身份验证机制。所以我手动将两个中间件添加到机架堆栈中。
由于我在config/application.rb
中添加了它们,它们几乎被添加到堆栈的远端,即在Warden
中间件本身之后。但是Warden
中间件非常清楚它需要在堆栈中使用Session和Cookie管理器before
。这样任何会话都会更改它会使将最终序列化到会话和cookie中。
这导致失败应用程序被丢弃的会话更改。因此,会话永远不会被清除并导致重定向循环。以下步骤将使其更加清晰。
Warden
中间件绕过它所经历的所有中间件。所以它错过了cookie和会话中间件)重复步骤5-8,直到浏览器因错误而停止。
这是一个序列图,我为任何对细节感兴趣的人捕获整个流程。
@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将重定向到您想要的任何页面。
无论如何,很高兴您仍然可以通过调整中间件中的某些部分来解决问题。
问候!