在使用Rails和Devise注册后,将用户登录到其子域

我在我的Rails 3应用程序中使用Devise进行身份validation。 该应用程序使用PostgreSQL模式和Apartment gem来促进多租户。

创建帐户 ,登录和退出特定子域的工作正常。 用户只能在子域上登录其特定帐户,这很棒。

这是我遇到问题的地方……

全新用户点击注册url:

http://foo.com/signup

默认情况下,当他们单击“提交”时,将创建新帐户,但会将用户发送到:

http://foo.com/dashboard

相反,我希望他们去:

http://myaccount.foo.com/dashboard

为了实现这一点,我覆盖了registrations_controller.rb文件中的after_sign_up_path_for方法:

 def after_sign_up_path_for(resource) root_url(:subdomain => resource.account.subdomain) end 

这按预期工作 – 它加载正确的URL – 但用户的会话是为根域(foo.com)而不是子域创建的,因此要求用户登录。

我发现的一个建议是将config/initializers/session_store.rb更改为:

 config.session_store :cookie_store, :key => '_domain_session', :domain => :all 

但这允许任何人登录任何子域的帐户,这显然不是很酷。

问题:如何确保注册时创建的会话对注册过程中创建的子域有效

您可以在config.session_store中使用domain: :all选项,只需按照注释中某些人的建议使用before_action。

所以你仍然会在config / initializers / session_store.rb或config / application.rb中获得代码:

 config.session_store :cookie_store, :key => '_domain_session', :domain => :all 

然后在application_controller中添加以下代码:

 #app/controllers/application_controller.rb before_action :check_subdomain def check_subdomain unless request.subdomain == current_user.account.subdomain redirect_to root_path, alert: "You are not authorized to access that subdomain." end end 

覆盖设计会话控制器。

使用确切路径 app/controllers/devise/sessions_controller.rb创建一个文件

覆盖该控制器中的sessions_controller类。 粘贴在链接中找到的代码中。 https://github.com/plataformatec/devise/blob/master/app/controllers/devise/sessions_controller.rb

 class Devise::SessionsController < DeviseController # copy-paste the devise session controller below. ... end 

编辑create操作以满足您的需求。

 def create self.resource = warden.authenticate!(auth_options) set_flash_message(:notice, :signed_in) if is_flashing_format? sign_in(resource_name, resource) yield resource if block_given? respond_with resource, :location => after_sign_in_path_for(resource) end 

我想知道我是否能弄清楚如何完成这项工作,但我确信你想要的结果可以通过覆盖设计会话控制器来实现。

编辑

如果您使用的是跨子域Cookie,则可以使用before_filter强制执行子域会话。 例如

 before_action do redirect_to root_path, alert: 'That subdomain does not belong to you' if request.subdomain != current_user.subdomain end