Страницы

Поиск по вопросам

четверг, 23 января 2020 г.

Переключение пользователя БД

#ruby_on_rails #activerecord


У меня возникла необходимость ограничивать доступ к данным не только на уровне приложения
но и на уровне БД.
Я сделал все следующим образом в application_controller.rb:

before_filter :set_db_connection

def set_db_connection
    unless current_user.nil?
      ActiveRecord::Base.establish_connection(
        :adapter  => "oracle_enhanced",
        :database     => "host/XE",
        :username => current_user.db_login,
        :password => current_user.db_password

      )
      ActiveRecord::Base.connection.execute('alter session set current_schema = db_schema')
    end
  end


Правильно ли я решил данную задачу, и не может ли возникнуть проблем с таким решением?
    


Ответы

Ответ 1



Я бы сделал так def set_db_connection if current_user.present? ActiveRecord::Base.clear_cache! ActiveRecord::Base.establish_connection( :adapter => "oracle_enhanced", :database => "host/XE", :username => current_user.db_login, :password => current_user.db_password ) ActiveRecord::Base.connection.execute('alter session set current_schema = db_schema') end end и поглядел посмотрел нет ли того что мне нужно в геме db-charmer

Ответ 2



Честно говоря, не уверен в том, что это будет корректно работать в продакшене. Например unicorn создаёт сразу несколько воркеров, которые сразу подключаются к базе. Как минимум, такой подход приведёт к тому, что будут тратиться дополнительные ресурсы на создаение нового подключения буквально при каждом обновлении страницы. Не говоря уж про дополнительные административные расходы на поддержание в актуальном состоянии логина и пароля от базы в таблице пользователей. Вообще задача сама по себе неправильная. Согласно концепции Rails база данных - "тупое" хранилище. Добавлять ограничение (как и любую другую логику) в базу данных - оверхед. Плюс стоит учитывать, что если приложение попытается сделать что-то, что запрещено на уровне бд - пользователь получит 500. Если возникает подобная задача, я бы начал с того, что: Посмотрел имеющиееся гемы для авторизации пользователей. Например cancancan или pundit. Они достаточно мощные и помогают достаточно гибко решить многие задачи авторизации. Пересмотрел структуру проекта. Если не помогло 1 и 2 и всё равно очень надо настраивать права на уровне СУБД - поднял бы несколько копий приложения и разнёс их по поддоменам. А с основого домена редиректил бы на поддомен, в зависимости от текущего пользователя. Например: clients.my-site.ru - поддомен для клиентов, где в конфиге БД задан пользователь с ролью "клиент". admins.my-site.ru - поддомен для админстраторов, где в конфиге БД задан пользователь с ролью "admin". т.д. Но это очень сложный и скользкий путь. Следует как следует подумать прежде чем идти по нему. UPD Согласно статье на офф. сайте оракла, нет стандартного способа сделать Pass-Through. Попытки (в том числе и предложеная автором вопроса) приведут к потерям производительности.

Комментариев нет:

Отправить комментарий