2

我的客户有一个现有的数据库,其中每个用户都有自己的数据库用户,他希望每个用户都使用自己的数据库用户登录到 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

我怎样才能做到这一点,ActiveRecord或者是否有更好的解决方案来解决这个问题?或者是否有其他 ORM 映射器可以更好地解决这个问题?

我无法更改数据库或每个用户都有自己需要登录的数据库用户这一事实,因为我的客户确实将此结构用于其他应用程序:(

这是一个 Postgres 数据库。和 Rails 3.2.13 (JRuby)。

4

2 回答 2

1

首先,我从来没有开发过这种身份验证系统,但如果我必须这样做,我可能会选择Warden,这是一个集成为机架中间件的身份验证系统。

Warden 允许建立您自己的身份验证策略。所以我为你的情况做了一个例子,但请注意它不起作用。这只是为了清楚起见。

这个想法是在机架中间件中使用给定的用户名/密码重新配置您的数据库池。机架中间件是请求中调用的第一个组件,所以我认为它应该避免性能问题。

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

然后在 Rails 配置文件中配置 Warden。

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

再一次,这只是一个原型,让您了解如何解决问题。我希望这会对你有所帮助。

于 2013-06-07T09:09:24.960 回答
0

这不是在每个用户的每个请求上重置连接的好选择。最重要的是它会丢失数据库缓存,因为您必须在每个请求中启动连接。

最好尝试使用 Mongodb(如果可能),其中每条记录都属于一个用户,并且该用户的所有内容都将在该记录下。如果您正在尝试开发系统,则可以使用此解决方案。具有巨型数据库的现有系统可能认为这种解决方案是不可能的:)

于 2013-06-07T08:33:41.960 回答