1

我将 Rails 3.2.8 与 Devise 2.1.2 一起使用。

如果用户仍在应用程序中时会话超时,则下次用户单击应用程序中的某些内容时,它会重定向到登录页面。然而, 的价值session[:user_return_to]往往不是我所期望的。在试图追查原因时,我发现 Devise(或 Warden)在收到 401 错误后正在执行两个s。 GET

例如,如果用户正在编辑用户并在会话超时后单击更新,则日志如下所示:

Started PUT "/users/9f276de6-2175-11e3-b8ce-01413834ba1d" for 127.0.0.1 at 2013-10-11 16:43:36 -0700
Processing by UsersController#update as HTML
  Parameters: {"utf8"=>"?", "authenticity_token"=>"+JP3qXGyUEodmmlLQtpOJpxF8JuEg5sp4Iyjit784Ms=", "user"=>{"first_name"=>...}
  User Load (1.5ms)[0m  SELECT "users".* FROM "users" WHERE "users"."id" = '9b5f6b2e-40bc-31e3-b199-0141337836d6' LIMIT 1
Completed 401 Unauthorized in 9ms

Started GET "/users/9f276de6-2175-11e3-b8ce-01413834ba1d" for 127.0.0.1 at 2013-10-11 16:43:36 -0700
Processing by UsersController#show as HTML
  Parameters: {"id"=>"9f276de6-2175-11e3-b8ce-01413834ba1d"}
Completed 401 Unauthorized in 1ms

Started GET "/users/sign_in" for 127.0.0.1 at 2013-10-11 16:43:36 -0700
Processing by Devise::SessionsController#new as HTML
  Rendered devise/shared/_links.erb (7.2ms)
  Rendered devise/sessions/new.html.erb within layouts/application (21.8ms)
  Rendered layouts/_header.html.erb (7.5ms)
  Rendered layouts/_flash_messages.html.erb (0.1ms)
  Rendered layouts/_footer.html.erb (1.3ms)
Completed 200 OK in 174ms (Views: 171.8ms | ActiveRecord: 0.0ms)

GET第一次来自哪里,即#show第一次身份验证失败后如何以及为什么被调用?

如果我可以先摆脱它GET,我希望session[:user_return_to]保持设置为/users/{:id}/edit路径,这可能是用户在重新验证后想要去的地方。实际上,session[:user_return_to]设置为/users/{:id}这样他们在重新登录时不会回到编辑模式。

顺便说一句,即使失败的请求是 aGET而不是 a ,在它进入登录页面之前PUT我仍然会看到一个额外的。GET

4

1 回答 1

1

所以基本上这是这里报告的错误 #2421:

store_location!() 方法在超时后获取错误的位置

已通过修复 #2427 解决:

如果在超时后最新请求不是 GET,则将用户重定向到引荐来源网址

据我所知,该修复程序直到 Devise 3.0.0 才发布。

供将来参考的摘要

设计 2.1.2 在device/failure_app.rb中有这个例程:

def redirect_url
  if warden_message == :timeout
    flash[:timedout] = true
    attempted_path || scope_path
  else
    scope_path
  end
end

使用该代码,attempted_path是从 PUT 请求设置的,因此第一个重定向尝试对 PUT 使用的 URI 执行 GET(在本例中为/users/{:id})。当与 GET 一起使用时,该 URI 会调用该#show操作。

该代码已更新为:

def redirect_url
  if warden_message == :timeout
    flash[:timedout] = true
    path = if request.get?
      attempted_path
    else
      request.referrer
    end
    path || scope_path
  else
    scope_path
  end
end

看起来它仍然会在超时时执行双重重定向,但对于 PUT,它将使用request.referrer(在这种情况下,/users/{:id}/edit),所以session[:user_return_to]应该正确设置。

2013 年 10 月 25 日更新 我现在已经升级到 Devise 3.1.1。正如预期的那样,PUT 仍然会在超时时进行两次重定向,但session[:user_return_to]设置正确,因此用户在登录时会返回引荐来源网址。

于 2013-10-24T22:19:10.867 回答