Rails – 每个子域单独的数据库

我即将开始编写一个Rails应用程序,它允许客户端拥有一个单独的子域来访问我们的应用程序。 从数据安全的角度考虑,如果每个客户端的访问权限真正限制在他们的数据库中会很好,这样,如果生产代码中存在错误,他们只能访问自己的数据库,而不能访问任何其他数据库。客户端。

我知道如何做我想要的代码,但我想知道是否有一个更简单的解决方案,我可能会失踪。 您将如何保护客户端数据,以便在出现错误或黑客威胁时,他们的数据不太可能被暴露?

这是我用于解决这个问题的一些代码:

application_controller.rb

before_filter :set_database helper_method :current_website # I use the entire domain, just change to find_by_subdomain and pass only the subdomain def current_website @website ||= Website.find_by_domain(request.host) end def set_database current_website.use_database end # Bonus - add view_path def set_paths self.prepend_view_path current_website.view_path unless current_website.view_path.blank? end 

Website.rb

 def use_database ActiveRecord::Base.establish_connection(website_connection) end # Revert back to the shared database def revert_database ActiveRecord::Base.establish_connection(default_connection) end private # Regular database.yml configuration hash def default_connection @default_config ||= ActiveRecord::Base.connection.instance_variable_get("@config").dup end # Return regular connection hash but with database name changed # The database name is a attribute (column in the database) def website_connection default_connection.dup.update(:database => database_name) end 

希望这可以帮助!

我找到了一个更容易实现的不同解决方案,但假设您拥有每个子域的数据库:

application_controller.rb

 before_filter :subdomain_change_database def subdomain_change_database if request.subdomain.present? && request.subdomain != "www" # 'SOME_PREFIX_' + is optional, but would make DBs easier to delineate ActiveRecord::Base.establish_connection(website_connection('SOME_PREFIX_' + request.subdomain )) end end # Return regular connection hash but with database name changed # The database name is a attribute (column in the database) def website_connection(subdomain) default_connection.dup.update(:database => subdomain) end # Regular database.yml configuration hash def default_connection @default_config ||= ActiveRecord::Base.connection.instance_variable_get("@config").dup end 

这将切换到像mydb_subdomain这样的数据库。 这是一个完整的替换数据库选项,但它可以非常容易地推出多个版本。

事实certificate我刚刚问了一个非常相似的问题,但在开发过程中还有一些问题 – 我已经提出了三个关于如何安全地使用单个数据库的想法。

在我的脑海中,你可以使用不同的环境为每个子域运行一个新的服务器实例。

但这不会很好地扩展。

然而,前几个谷歌点击多个铁路数据库出现了一些新的建议。 将信息放在这些链接中为单个服务器实例提供了这种完全未经测试的解决方案。

您需要为databases.yml中的每个子域添加数据库条目。 然后将before_filter添加到应用程序控制器

更新! 示例动态重新加载数据库配置。 不幸的是,没有好的方法可以在不弄乱服务器内部的情况下使更新轨道更宽。 因此,必须在每个请求上重新加载数据库配置。

此示例假定databases.yml中的数据库条目以子域命名。

配置/ database.yml的

 login: &login adapter: mysql username: rails password: IamAStrongPassword! host: localhost production: <<: *login database: mysite_www subdomain1: <<: *login database: mysite_subdomain1 subdomain2: <<: *login database: mysite_subdomain2 ... 

app / controllers / application_controller.rb需要'erb'prefore_filter:switch_db_connection

 def switch_db_connection subdomain = request.subdomains.first ActiveRecord::Base.configurations = YAML::load(ERB.new(IO.read(Rails.configuration.database_configuration_file)).result) ActiveRecord::Base.establish_connection("mysite_#{subdomain}") end 

正如我所说,它完全没有经过考验。 但我没有预见到任何重大问题。 如果它不起作用,希望它能让你走上正轨。