【问题标题】:Devise: Have multiple controllers handle user sessions设计:让多个控制器处理用户会话
【发布时间】:2011-05-26 19:12:34
【问题描述】:

我正在运行带有 rails 3.0.7 的设计 1.3.4。我有两种用户可以登录的方式:使用网络应用程序和使用移动网络应用程序(通过 JSON API 调用)。第一种方法由默认设计会话控制器完美处理。身份验证的 API 调用方法需要在扩展我的Api::BaseController 的控制器中。所以,我这样写了第二个控制器:

class Api::UserSessionsController < Api::BaseController
  …
  def create
    user = warden.authenticate(:scope => :user)
    if user
      sign_in(:user, user)
    else
      # Do some error handling
    end
  end
end

由于Devise::Strategies::Authenticatable 中的valid_controller? 方法,尝试通过此方法登录失败。因为我已将默认控制器 (devise/sessions) 保留为用户的映射控制器,所以它不允许来自我的自定义控制器的身份验证。

我想将我的自定义功能整合到我自己的 Devise::SessionsController 子类中,但我需要 API 会话控制器来扩展 API::BaseController,所以我无法扩展 Devise::SessionsController也是。我不想将工作的、默认行为的网络应用身份验证方法放在 API 控制器中,尤其是因为这需要从设计控制器中复制它们。

有什么建议吗?我是否缺少一些允许多个控制器处理会话的配置? valid_controller? 方法进行 == 比较,而不是 .include?,所以我看不出它是如何工作的。

更新

这是一个糟糕的临时解决方法。我不喜欢它,所以我不会将它作为答案发布,但我认为它可能会为所有回答者类型提供思考:

在我的 create 方法的顶部,我可以覆盖 Devise 期望的会话控制器。

Devise.mappings[:user].controllers[:sessions] = params[:controller]

这是围绕 Devise 的预期功能(需要一个特定的控制器来创建会话),所以我不想保留它。我想知道这个约束是一种安全措施还是只是一种约定——如果是为了安全,这可能是相当糟糕的。

【问题讨论】:

    标签: ruby-on-rails-3 authentication devise warden


    【解决方案1】:

    我只能建议另一种解决方法(也许不那么糟糕?) 在初始化程序中,您可以覆盖 #valid_controller?,如下所示:

    require 'devise/strategies/authenticatable'
    require 'devise/strategies/database_authenticatable'
    
    class Devise::Strategies::DatabaseAuthenticatable
      def valid_controller?
        # your logic here
        true
      end
    end
    

    我也很想知道这个限制的原因

    【讨论】:

    • 这是个好主意。肯定比我的粗。我正在考虑修补设计以在 valid_controller 中执行 .include? 并在我的路线声明中提供一个数组。
    【解决方案2】:

    我正在使用带有 Rails 3.2.13 的 Devise 2.2.7。以上两种方法都对我不起作用:Devise::Strategies::DatabaseAuthenticatable 中的valid_vontroller? 方法不再存在。 Devise.mappings[:user].controllers[:sessions] 技巧对我也不起作用。

    在挖掘this thread之后,我找到了valid_params_request?,它负责确保请求应该通过身份验证系统发送。有一个辅助方法allows_params_authentication!,它使Devise::SessionsController 能够处理身份验证请求。

    您可以通过以下方式从任何控制器对用户进行身份验证:

    def signin
      allow_params_authentication!
      authenticate_user!
    end
    

    如果您想在认证失败时重定向到自定义页面:

    resource = warden.authenticate!({
      :scope => :user,
      :recall => "#{controller_path}#login"
    })
    sign_in(:user, resource)
    

    我发现需要在 Devise::SessionsController 的子类之外处理身份验证,方法是开发一个与 Spree Commerce 一起工作的引擎,Spree Commerce 已经实现了设计身份验证。

    【讨论】:

      猜你喜欢
      • 2011-12-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-11-20
      • 1970-01-01
      • 2020-04-02
      • 1970-01-01
      相关资源
      最近更新 更多