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 を使用すると、独自の認証戦略を構築できます。そのため、あなたのケースの例を作成しましたが、機能しないことに注意してください。わかりやすくするためです。

アイデアは、ラック ミドルウェアで特定のユーザー名/パスワードを使用してデータベース プールを再構成することです。Rack ミドルウェアはリクエストで最初に呼び出されるコンポーネントなので、パフォーマンスの問題を回避する必要があると思います。

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

これは、ユーザーごとにリクエストごとに接続をリセットするのには適していません。最も重要なことは、各リクエストで接続を開始する必要があるため、db キャッシュが失われることです。

各レコードがユーザーに属し、そのユーザーのすべてがそのレコードの下にある Mongodb を (可能であれば) 使用することをお勧めします。システムを開発しようとしている場合、このソリューションは可能です。巨大なデータベースを備えた既存のシステムでは、このソリューションは不可能と見なされる可能性があります:)

于 2013-06-07T08:33:41.960 に答える