如何创建管理子域来管理 Rails 中的子域
我正在使用 AuthLogic 和 dhh 在 这篇博文,一切都很顺利,符合预期。我想要弄清楚的是如何创建一个像“admin”或“host”这样的子域,该子域将让用户通过 AuthLogic 进行身份验证(这可能很简单,无需提及)来管理子域。所以基本上,所有子域都会正常运行,除了 admin.site.com ,它会转到自己的控制器和布局。
dhh 建议抛出一个异常来重定向,但我不确定它会去哪里,似乎没有对我来说很简单,有什么想法吗?
编辑 我认为我使用 AuthLogic 的事实在这里很重要,因为一旦经过身份验证的 AuthLogic 将用户发送到 /account,子域逻辑不会将用户转发到任何地方 - 所以我的问题可能与如果user 是 root 用户,登录到 admin 子域。
这是我们迄今为止实现的代码
公司模式
class Company < ActiveRecord::Base
has_many :users
has_many :brands, :dependent => :destroy
validates_presence_of :name, :phone, :subdomain
validates_format_of :subdomain, :with => /^[A-Za-z0-9-]+$/, :message => 'The subdomain can only contain alphanumeric characters and dashes.', :allow_blank => true
validates_uniqueness_of :subdomain, :case_sensitive => false
validates_exclusion_of :format, :in => %w( support blog billing help api www host admin manage ryan jeff allie), :message => "Subdomain {{value}} is not allowed."
before_validation :downcase_subdomain
protected
def downcase_subdomain
self.subdomain.downcase! if attribute_present?("subdomain")
end
end
子域公司模块
module SubdomainCompanies
def self.included( controller )
controller.helper_method(:company_domain, :company_subdomain, :company_url, :company_account, :default_company_subdomain, :default_company_url)
end
protected
# TODO: need to handle www as well
def default_company_subdomain
''
end
def company_url( company_subdomain = default_company_subdomain, use_ssl = request.ssl? )
http_protocol(use_ssl) + company_host(company_subdomain)
end
def company_host( subdomain )
company_host = ''
company_host << subdomain + '.'
company_host << company_domain
end
def company_domain
company_domain = ''
company_domain << request.domain + request.port_string
end
def company_subdomain
request.subdomains.first || ''
end
def default_company_url( use_ssl = request.ssl? )
http_protocol(use_ssl) + company_domain
end
def current_company
Company.find_by_subdomain(company_subdomain)
end
def http_protocol( use_ssl = request.ssl? )
(use_ssl ? "https://" : "http://")
end
end
应用程序控制器
class ApplicationController < ActionController::Base
include SubdomainCompanies
rescue_from 'Acl9::AccessDenied', :with => :access_denied
helper :all # include all helpers, all the time
protect_from_forgery # See ActionController::RequestForgeryProtection for details
helper_method :current_user_session, :current_user, :current_company_name
filter_parameter_logging :password, :password_confirmation
before_filter :check_company_status
protected
def public_site?
company_subdomain == default_company_subdomain
end
def current_layout_name
public_site? ? 'public' : 'login'
end
def check_company_status
unless company_subdomain == default_company_subdomain
# TODO: this is where we could check to see if the account is active as well (paid, etc...)
redirect_to default_company_url if current_company.nil?
end
end
end
I am using AuthLogic and the subdomain method that dhh covered in this blog post, everything is working great, and as expected. What I'm trying to figure out is how to create a subdomain like 'admin' or 'host' that will have a user authenticated from AuthLogic (this may be trivial and unnecessary to mention) that will manage the subdomains. So basically, all subdomains will act normally, except admin.site.com which will go to its own controller and layout..
dhh suggested just throwing in an exception to redirect, but I'm not sure where that goes, it didnt seem that simple to me, any ideas?
EDIT
I think that the fact I am using AuthLogic is important here, because the subdomain logic isnt forwarding users anywhere, once authenticated AuthLogic sends the user to /account - so my question may be related to how do I tell AuthLogic to a different spot if the user is a root user, logging into the admin subdomain..
Here is the code we have implemented thus far
Company Model
class Company < ActiveRecord::Base
has_many :users
has_many :brands, :dependent => :destroy
validates_presence_of :name, :phone, :subdomain
validates_format_of :subdomain, :with => /^[A-Za-z0-9-]+$/, :message => 'The subdomain can only contain alphanumeric characters and dashes.', :allow_blank => true
validates_uniqueness_of :subdomain, :case_sensitive => false
validates_exclusion_of :format, :in => %w( support blog billing help api www host admin manage ryan jeff allie), :message => "Subdomain {{value}} is not allowed."
before_validation :downcase_subdomain
protected
def downcase_subdomain
self.subdomain.downcase! if attribute_present?("subdomain")
end
end
SubdomainCompanies Module
module SubdomainCompanies
def self.included( controller )
controller.helper_method(:company_domain, :company_subdomain, :company_url, :company_account, :default_company_subdomain, :default_company_url)
end
protected
# TODO: need to handle www as well
def default_company_subdomain
''
end
def company_url( company_subdomain = default_company_subdomain, use_ssl = request.ssl? )
http_protocol(use_ssl) + company_host(company_subdomain)
end
def company_host( subdomain )
company_host = ''
company_host << subdomain + '.'
company_host << company_domain
end
def company_domain
company_domain = ''
company_domain << request.domain + request.port_string
end
def company_subdomain
request.subdomains.first || ''
end
def default_company_url( use_ssl = request.ssl? )
http_protocol(use_ssl) + company_domain
end
def current_company
Company.find_by_subdomain(company_subdomain)
end
def http_protocol( use_ssl = request.ssl? )
(use_ssl ? "https://" : "http://")
end
end
Application Controller
class ApplicationController < ActionController::Base
include SubdomainCompanies
rescue_from 'Acl9::AccessDenied', :with => :access_denied
helper :all # include all helpers, all the time
protect_from_forgery # See ActionController::RequestForgeryProtection for details
helper_method :current_user_session, :current_user, :current_company_name
filter_parameter_logging :password, :password_confirmation
before_filter :check_company_status
protected
def public_site?
company_subdomain == default_company_subdomain
end
def current_layout_name
public_site? ? 'public' : 'login'
end
def check_company_status
unless company_subdomain == default_company_subdomain
# TODO: this is where we could check to see if the account is active as well (paid, etc...)
redirect_to default_company_url if current_company.nil?
end
end
end
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
查看 subdomain-fu 它允许您根据子域路由到不同的控制器和操作。我已经就这个主题做了Railscasts Episode。
它可能看起来像这样。
这需要在路由列表中位于足够高的位置,以便在它之前没有其他内容匹配。
Look into subdomain-fu which allows you to route to different controllers and actions based on the subdomain. I have done a Railscasts Episode on the subject.
It might looks something like this.
This will need to be high enough up in the routes list so nothing else is matched before it.
对于 RAILS 2.3: 您可以下载完整的示例应用程序(带有分步教程),展示如何使用 Devise gem 进行身份验证来实现管理子域、主域和多个用户子域以及用于管理子域的 subdomain-routes gem。链接如下:Rails 2.3 的子域身份验证。
对于 RAILS 3: 这是 具有身份验证功能的 Rails 3 子域的完整示例实现(以及详细的教程)。在 Rails 3 中执行此操作比在 Rails 2 中容易得多(无需插件)。
FOR RAILS 2.3: You can download a full example app (with a step-by-step tutorial) showing how to implement an admin subdomain, a main domain, and multiple user subdomains using the Devise gem for authentication and the subdomain-routes gem for managing subdomains. Here's the link: subdomain authentication for Rails 2.3.
FOR RAILS 3: Here's a complete example implementation of Rails 3 subdomains with authentication (along with a detailed tutorial). It's much easier to do this in Rails 3 than in Rails 2 (no plugin required).