我的客户有一个现有的数据库,每个用户都拥有自己的数据库用户,他希望每个用户都使用自己的数据库用户登录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)。
答案 0 :(得分:1)
首先,我从未开发过这种身份验证系统,但如果必须,我可能会选择Warden,这是一个集成为rack middleware的身份验证系统。
守望者允许建立自己的authentication strategies。所以我为你的案子做了一个例子,但要注意它不起作用。这只是为了清楚起见。
我们的想法是在机架中间件中使用给定的用户名/密码重新配置数据库池。机架中间件是请求中调用的第一个组件,因此我认为它应该避免性能问题。
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
这再一次只是一个原型,让您了解如何解决问题。我希望这会对你有所帮助。
答案 1 :(得分:0)
对于每个用户的每个请求重置连接不是一个好的选择。最重要的是,它会丢失数据库缓存,因为您必须在每个请求中启动连接。
最好尝试使用Mongodb(如果可能),其中每条记录都属于一个用户,该用户的所有内容都将在该记录下。如果您正在尝试开发系统,则可以使用此解决方案。拥有巨型db的现有系统可能会认为这个解决方案是不可能的:)