Rails 4应用程序中的子域名

时间:2014-07-10 04:25:07

标签: ruby-on-rails ruby-on-rails-4 devise subdomain

今天我遇到了一个相当奇怪的现象。在开发一个Rails应用程序时,每个用户都有自己的子域,并尝试使用Devise来完成它,我遇到了也没有注册任何路由到根页面的子域。因此,例如,即使没有(显式)子域,它也会将我路由到主应用程序页面。也许这与我的特定设置有关?我也试过一个新的Rails项目,但我得到了相同的结果。有人能为我澄清一下吗? Railscasts没有做到这一点。

此外,现在我正在使用WEBrick,即使这不是我将在生产中使用的,我正在使用域lvh.me来访问子域。

感谢您的帮助。

编辑:这是我的routes.rb文件:

Rails.application.routes.draw do
    devise_for :users
    root 'static_page#index'
end

我从Devise wiki中遵循了这个指南: https://github.com/plataformatec/devise/wiki/How-to:-Scope-login-to-subdomain

所以我做的是通过迁移删除了电子邮件的唯一性,然后我添加了:子域到request_keys,如下所示:

devise :database_authenticatable, :recoverable, :rememberable, :trackable, :timeoutable, request_keys: [:subdomain]

然后我继续覆盖“find_for_authentication”功能,如下所示:

def self.find_for_authentication(conditions={})
    conditions[:account_id] = Account.find_by_subdomain(conditions.delete(:subdomain)).id
    super(conditions)
end

这就是总结它。

编辑: 我一直在乱搞,我发现了问题。 'root'指令将所有子域引用到我的域。因此,如果我从routes.rb中删除root,每个子域都会导致RouteError。我记得在我的应用程序中为Devise需要一个根。所以我不确定这是Devise的行为还是root。

2 个答案:

答案 0 :(得分:4)

您可能遇到几个问题

首先,您需要了解Devise在登录后重定向您的用户的方式,其次是如何在Rails中路由子域。

-

<强>设计

默认情况下,Devise routes to current_user_path(通常表示users#show)或您路线中的某些内容:

def after_sign_in_path_for(resource)
  current_user_path
end

这意味着当您接受用户的登录时,他们将被带到自己的路径。根据您的路线,这通常意味着主站点(没有子域)用户的路径(domain.com/users/56)或其他东西。

在你的问题中没有任何具体细节,我只能推测这一点。

-

<强>子站点

刚刚开发了一些支持子域名的应用,您应该考虑路由到子域名。

用户登录后,需要将其路由到特定的subdomain。这样做的方法是使用constraint in your routes

#config/routes.rb
constraints { subdomain: 'admin' } do
    resources :photos
end

我们发现您无法使用常规路由路径执行此操作 - 您必须使用url(不是path帮助程序)。例如:

photos_path(subdomain: current_user.name) #-> does not work (path is relative)
photos_url(subdomain: current_user.name) #-> will route to http://name.lvh.me:3000

您必须记住的是,如果您要将流量重定向/路由到不同的子域,则需要引用帮助程序的url形式,而不是path引用。

因此,如果您按照上面显示的after_sign_in_path_for进行操作,则需要执行以下操作:

def after_sign_in_path_for(resource)
   root_url(subdomain: resource.name)
end

-

<强>会话

最后,您希望确保您的Devise会话cookie在设置后仍保持初始化状态。我们发现默认情况下不会处理子域名,因此您必须确保它们可以满足:

Share session (cookies) between subdomains in Rails?

#config/initializers/session_store.rb
YOUR_APP_NAME::Application.config.session_store :cookie_store, key: '_app_name_session', domain: :all, tld_length: 2 

答案 1 :(得分:1)

我手动解决了。我发现routes.rb中的'root'指令接受来自每个子域的请求。最后,我实现了一个自定义约束,并将其添加到routes.rb文件中devise_for的约束中。这充分解决了我的问题。谢谢大家的帮助!

更新:

在回复要求我的代码的评论时:我们设置了一个系统,每个帐户(企业帐户)都有自己的子域名,每个企业帐户都有很多用户。我的子域约束看起来像

<强> LIB / subdomain.rb

class Subdomain
  def self.matches?(request)
    request.subdomain.present? && Account.exists?(subdomain: request.subdomain)
  end
end

然后在我的config / routes.rb中,我使用该约束来路由请求:

<强>配置/ routes.rb中

require 'Subdomain'

Rails.application.routes.draw do
  # Some routes...
  constraints(Subdomain) do
    devise_for :users, controllers: {:sessions => 'session'}
    root 'dashboard#index'
    # More subdomain constrained routes...
  end
end

在我发布的原始问题中,我已经展示了其余的设置。我希望这有助于某人。