Rails - отдельная база данных на поддомен - PullRequest
13 голосов
/ 21 октября 2009

Я собираюсь начать писать приложение на Rails, которое позволит клиентам иметь отдельный поддомен для доступа к нашему приложению. Думая с точки зрения безопасности данных, было бы хорошо, если бы доступ каждого клиента был действительно ограничен их базой данных, таким образом, если бы была ошибка в рабочем коде, они могли бы получить доступ только к своей собственной базе данных, а не к какой-либо другой базе данных. клиенты.

Я знаю код, объясняющий, как делать то, что я хочу, но мне было интересно, есть ли более простое решение, которое я мог бы упустить. Как бы вы защитили данные клиента, чтобы в случае ошибки или хакерской угрозы их данные были менее подвержены риску?

Ответы [ 4 ]

20 голосов
/ 22 октября 2009

Вот код, который я использую для этой самой проблемы:

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

Надеюсь, это поможет!

4 голосов
/ 23 июля 2011

Я нашел другое решение, которое работает немного проще, но предполагает, что у вас есть база данных для каждого субдомена:

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. Это полный вариант замены базы данных, но он позволяет легко развернуть несколько версий.

0 голосов
/ 22 октября 2009

Оказывается, я только что задал очень похожий вопрос , но чуть дальше в процессе разработки - я включил три идеи о том, как безопасно использовать одну базу данных там.

0 голосов
/ 22 октября 2009

Вдобавок ко всему, вы можете запустить новый экземпляр сервера для каждого субдомена в другой среде.

Но это не очень хорошо масштабируется.

Однако первые несколько хитов Google для баз данных с несколькими рельсами приводят некоторые новые предложения. Объединение информации в этих ссылках обеспечивает это полностью непроверенное решение для одного экземпляра сервера.

Вам необходимо добавить запись базы данных для каждого субдомена в вашем database.yml. Затем добавьте before_filter к вашему контроллеру приложения

Обновление! Пример динамически перезагружает конфигурации базы данных. К сожалению, нет хорошего способа сделать рельсы обновлений широкими, не связываясь с внутренностями вашего сервера. Таким образом, конфигурация базы данных должна будет перезагружаться при каждом запросе.

В этом примере предполагается, что записи базы данных в database.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
...

приложение / контроллеры / application_controller.rb требовать 'erb' before_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

Как я уже сказал, это полностью не проверено. Но я не предвижу никаких серьезных проблем. Если это не сработает, мы надеемся, что вы на правильном пути.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...