3

顧客ごとにデータベースを持つレガシー アプリケーションを書き直しています。各顧客には、独自の認証とユーザー セットがあります。したがって、django の認証はデフォルトのみを使用するように設定されているため、カスタム認証バックエンドが必要になります。リクエストごとに URL を調べ、そこにある情報を抽出してリクエストに database_name を設定するミドルウェアを作成しました。

カスタム認証バックエンドの処理中にリクエストにアクセスできた場合、データベース呼び出しを簡単に実行できますが、user = User.objects.using(request.db).get(username=username)これを実現する簡単な方法はありません。私はここでそれに対する答えを見てきました: backend.get_user から request.session にアクセスしますが、これはスレッドセーフではないように見えるので、その道をたどりたくありません。

まだdjango-authを使用していると私が見ることができる唯一の解決策は、データベース名をクラス属性として使用するように設定する各顧客の認証バックエンドを持つことです。次に、request.session['_auth_user_backend'] を顧客固有のバックエンドに設定するカスタム ログイン関数を作成します。したがって、各リクエストで get_user(user_id) が呼び出されると、リクエスト元のデータベースを認識している顧客のバックエンドが使用されます。

可能であれば、顧客ごとに認証バックエンドを管理する必要は避けたいと考えています。これを行うより良い方法はありますか?

4

2 に答える 2

8

認証バックエンドは QuerySet メソッドを呼び出していないため、スレッド ローカル変数といくつかのミドルウェアを備えたデータベース ルーターusingを使用して、変数を顧客のデータベース名に設定できます。ミドルウェアは、認証ミドルウェアの前に配置する必要があります。

スレッド ローカル変数はスレッド セーフです。スレッド ローカル グローバル変数を作成します。

リクエストのパスをたどっていた場合、次のようになります。

  1. リクエストがdjangoに当たる
  2. カスタム ミドルウェアは、URL からデータベース名を取得し、それをスレッド ローカル グローバル変数に設定します。
  3. django 認証ミドルウェアが起動し、 query を実行してユーザーを設定しますUser.object.get(id=user_id)。これは、以前のミドルウェアで設定されたスレッド ローカル グローバル変数を返すだけのデータベース ルーターを使用します。

  4. リクエストは、django スタックの残りの部分に続きます。

たとえば、次のモジュールがあります。

my_app/middleware.py

from threading import local

my_local_global = local()

class CustomerMiddleware(object):
    def process_request(self, request):
        my_local_global.database_name = get_database_name(request)

my_app/routers.py

from middleware import my_local_global

class MultiCustomerRouter(object):
    def db_for_read(self, model, **hints):
        return my_local_global.database_name

設定.py

...
MIDDLEWARE_CLASSES = (
 'django.middleware.common.CommonMiddleware',
 'django.contrib.sessions.middleware.SessionMiddleware',
 'django.middleware.csrf.CsrfViewMiddleware',
 'my_app.middleware.CustomerMiddleware',
 'django.contrib.auth.middleware.AuthenticationMiddleware',
 'django.contrib.messages.middleware.MessageMiddleware',
)

DATABASE_ROUTERS = ['my_app.routers.MultiCustomerRouter']
...
于 2012-10-01T12:21:21.820 に答える
2

Django データベース ルーターを使用してこれを制御できる可能性があります。どのユーザーがどのデータベースにアクセスするかがわかっている場合は、ユーザー モデルのロジックに基づいて簡単に定義できます。

于 2012-09-28T15:02:37.770 に答える