设计 - 为多个用户单一登录表单

时间:2012-09-21 14:36:04

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

我有两个Devise模型,User和Business;我希望两者都能够使用单一登录形式登录。我正在使用骨干js,我有一个自定义的视图,所以视图不是一个问题。 ajax请求用于登录,它按预期适用于用户,但不适用于企业。

我搜索了谷歌并遇到了一些提及使用STI来解决这个问题的解决方案,但该项目已经完成,我现在无法做出这样的改变。我正在考虑覆盖Devise会话控制器并且:

  1. 检查给定的电子邮件地址是否为用户,然后使用Warden对用户进行身份验证。
  2. 如果找不到使用该电子邮件的用户,则使用Warden对商业模式进行身份验证。
  3. 我无法弄清楚如何更改代码来实现上述目标,我不知道warden如何工作以及我需要调整哪些params来实现上述功能,需要调用哪些函数。任何人都可以指出我正确的方向或提供一个例子,说明我应该如何向前推进。

    感谢。

3 个答案:

答案 0 :(得分:6)

别担心,你不会被困住。

我认为您最好的选择是覆盖Devise的会话控制器并更改会话的“新”和“创建”方法。

所以在你自己的“sessions_controller.rb”中,你会有这样的东西:

class SessionsController < Devise::SessionsController
  # GET /resource/sign_in
  def new
    resource = build_resource(nil, :unsafe => true)
    clean_up_passwords(resource)
    respond_with(resource, serialize_options(resource))
  end

  # POST /resource/sign_in
  def create
    resource = warden.authenticate!(auth_options)
    set_flash_message(:notice, :signed_in) if is_navigational_format?
    sign_in(resource_name, resource)
    respond_with resource, :location => after_sign_in_path_for(resource)
  end
end

在你的路线中,你会使用类似的东西(取决于你命名的用户模型):

devise_for :users, :controllers => {
    :sessions => 'sessions'
}


devise_for :businesses, :controllers => {
    :sessions => 'sessions'
}

以上会话控制器根本不是自定义的。我不知道你的代码,所以我无法真正帮助那里。但基本步骤是:

  1. 检查auth_optionsresource_name变量,了解它们如何存储数据。
  2. 如果在Users表中找不到resource,请添加条件逻辑以更改这些变量。
  3. 设计很棒,角色很棒,但有时拥有一个用户模型,甚至使用STI,都没有意义。我很快就在这个问题上写了一篇更长的帖子,因为我在最近的一个项目中处理了它。

答案 1 :(得分:4)

请考虑仅使用用户模型,并使用CanCanRolify来满足每种类型用户的独特需求。这可能意味着从一些代码开始,但从长远来看可能更容易维护。

不要只听我的话。 Here's a related question with good responses.

答案 2 :(得分:4)

我最近想出了这个彻底的黑客来完成这项工作。我的建议是强烈考虑具有角色的单个用户模型,但这是有效的 - 至少对于当前版本的Devise。

https://gist.github.com/jeremyw/5319386

如果你monkeypatch或以其他方式覆盖这样的默认行为,请确保你有一个好的测试套件,以防你想尝试升级Devise。