Rails / Devise在未授权和已登录之间反弹

时间:2016-06-23 18:22:54

标签: ruby-on-rails devise

我在我的Rails 4.2.6应用程序中使用了Devise 3.5.6和一个StaffUser类,很长一段时间没有问题。该应用可通过staff.example.com访问。

现在我已经创建了第二个ClientUser课程,以便通过client.example.com访问该应用的单独部分。

两个用户类都有自己的作用域视图和扩展会话控制器(在ClientUser的情况下,这仅仅是为了覆盖使用的布局)。

我遇到的问题是登录的ClientUser通常会在受保护的网页成功加载之前多次循环/重定向以下步骤:

  • 请求/foo,回复是401 Unauthorized
  • 重定向到/client_users/session/new
  • 使用“您已登录”Flash消息
  • 重定向到/foo

这种情况发生在生产中的大多数请求中,但很少在开发中。

它会多次运行此循环(在浏览器中触发Chrome的“Too many redirects”警告),然后停在最初请求的页面上。用户在任何时候都没有机会再次登录,因此他们必须首先获得授权。

这似乎不会影响StaffUser

配置/ routes.rb中

constraints subdomain: 'client' do
  devise_for :client_users, controllers: {
    sessions: 'devise/client_sessions'
  }

  resources :client_app_object
end

constraints subdomain: 'staff' do
  devise_for :staff_users, controllers: {
    sessions: 'devise/staff_sessions'
  }

  resources :staff_app_object
end

配置/初始化/ devise.rb

config.scoped_views = true
config.default_scope = :staff_user

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

LIB /色器件/ custom_failure.rb

class CustomFailure < Devise::FailureApp
  def redirect_url
    if request.subdomain == 'staff'
      new_staff_user_session_url(subdomain: request.subdomain)
    elsif request.subdomain == 'client'
      new_client_user_session_url(subdomain: request.subdomain)
    else
      # incorrect/missing subdomain
      raise CustomFailureException
    end
  end

  ...
end

我的工作理论是,Devise正在尝试从会话中检索ClientUser,但是将其视为StaffUser,从而导致最初的401 Unauthorized。

这里会出现竞争条件吗?

设计如何知道要实例化哪个用户类?

由于

编辑1 - config / initializers / session_store.rb

Rails.application.config.session_store :cookie_store, key: '_my_session'

1 个答案:

答案 0 :(得分:0)

我发现我的问题的原因是我将默认的Devise控制器(和我的应用程序控制器)扩展到与模型的类名冲突的命名空间。具体为Client::*****Controller vs Client

将类名称空间更改为未使用的名称可解决冲突。

同样的问题还有其他副作用使问题混乱。这些包括扩展类中的before_action过滤器没有触发,可能是因为它们没有被正确扩展 - 尽管我还不知道为什么这种情况是静默地发生而且只是间歇性地发生。