2013-06-07 2 views
2

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

Для моделей этой базы данных я использую ActiveRecord::Base::establish_connection для соединения с именем пользователя и паролем формы входа.

Теперь я решил закрыть это соединение в after_filter, чтобы никто не мог получить это соединение из пула соединений. Но это не работает.

Я хочу что-то подобное в моем контроллере:

class Demo < ActiveRecord::Base 
    before_filter :connect 
    after_filter :close_connection 

    def action 
     # do some stuff with the database 
    end 
end 

Как я могу achive это с ActiveRecord или есть лучшее решение для этой проблемы? Или есть другой конвертер ORM, который лучше для этой проблемы?

Я не могу изменить базу данных или тот факт, что каждый пользователь имеет свой собственный пользователь базы данных, что ему нужно войти в becuase мой клиент действительно использует эту структуру для других приложений :(

Это база данных Postgres . И Rails 3.2.13 (JRuby).

ответ

1

Во-первых, я никогда не разрабатывал такую ​​систему аутентификации, но если бы мне пришлось это сделать, вероятно, выберете Warden, который является системой аутентификации, интегрированной как rack middleware.

Warden позволяет создавать собственные authentication strategies. Поэтому я привел пример для вашего дела, но помните, что он не работает. Это просто для ясности.

Идея состоит в том, чтобы перенастроить пул базы данных с заданным именем пользователя/паролем в промежуточном программном обеспечении стойки. Rack middlewares являются первыми компонентами, вызванными в запросе, поэтому я думаю, что это должно избегать проблем с производительностью.

Warden::Strategies.add(:database_user) do 

    def valid? 
    ActiveRecord::Base.connected? 
    end 

    def authenticate! 
    # Disconnects all connections in the pool, and clears the pool. 
    ActiveRecord::Base.connection_pool.disconnect! 

    # Reconfigure the pool with the new username/password 
    config = Rails.application.config.database_configuration[Rails.env] 
    config['username'] = params[:username] 
    config['password'] = params[:password] 

    # Establish connection with the new configuration 
    ActiveRecord::Base.establish_connection(config) 

    # Check if the connection works 
    # It means that the username/password is correct 
    if ActiveRecord::Base.connected? 
     user = build_user(params[:username]) 
     success!(user) 
    else 
     fail!("Wrong username/password") 
    end 

    rescue # Errors thrown by Postgres 
    fail!("Wrong username/password") 
    end 

    private 

    def build_user(username) 
     OpenStruct.new({username: username}) # Dynamic object 
    end 
end 

Затем сконфигурируйте Warden в файле конфигурации Rails.

Rails.configuration.middleware.use RailsWarden::Manager do |manager| 
    manager.default_strategies :database_user 
    manager.failure_app = LoginController 
end 

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

+0

Спасибо за подсказку, я попробую это, когда вернусь в офис. – tbraun89

0

Это не является хорошим выбором для сброса соединения на каждый запрос для каждого пользователя. Самое главное, что теряет кэш дб, как вы должны инициировать соединение в каждом запросе.

Бетт попробуйте использовать Mongodb (если возможно), где каждая запись будет принадлежать пользователю, и все это будет находиться под этой записью. Эти решения возможны, если вы пытаетесь разработать систему. Существующая система с гигантским db может считать это решение невозможным :)

+1

Использование mongo можно сделать sharding –

+0

Это было в моем уме, но нет способа использовать mongodb :( – tbraun89

Смежные вопросы