Rails - отдельная база данных на субдомен - программирование
Подтвердить что ты не робот

Rails - отдельная база данных на субдомен

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

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

4b9b3361

Ответ 1

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

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

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

Ответ 2

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

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

Ответ 3

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

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

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

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

приложение/контроллеры/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

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

Ответ 4

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