今天我遇到了一个相当奇怪的现象。在开发一个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。
答案 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
在我发布的原始问题中,我已经展示了其余的设置。我希望这有助于某人。