1

私はFlask-HTTPAuthを使用して、基本認証を使用して2層認証システムを作成しようとしています。私のアプリケーションは2つのルートを持っています。/にはログインしているユーザーがアクセスでき、adminルートは/adminにアクセスできます。チェーンデコレータによるFlask-HTTPAuthを使用して特権ユーザーを作成する---コンテキストを失う?

次のようにだから私は(dbopsがデータベースに話を扱うだけの名前空間である場合)、コードの関連する部分と、デコレータを連鎖することによって、これを実施することを決定:

@auth.verify_password 
def verify_pw(lastname, password): 
    ln = lastname.lower() 
    if ln in dbops.list_users(): 
     hashed_pw = dbops.find_hashed_password(ln) 
     return bcrypt.checkpw(password.encode('utf8'), hashed_pw.encode('utf8')) 
    return False 

def must_be_admin(f): 
    @wraps(f) 
    def wrapper(*args, **kwargs): 
     if dbops.is_admin(auth.username()): 
      return f(*args, **kwargs) 
     return "Not authorized." 
    return wrapper 

@core.route("/") 
@auth.login_required 
def dataentry(): 
    return render_template("dataentry.html") 

@core.route("/admin") 
@must_be_admin 
@auth.login_required 
def admin(): 
    return render_template("admin.html") 

これは正常に動作していれば管理者ユーザーとしてログインしようとする人は、まず/ルートにアクセスします。ユーザー名とパスワードの入力を求めるメッセージが表示され、管理者ユーザーは/adminに行き、ログインした管理タスクを実行できます。

ただし、管理者が初めて/adminにアクセスすると、ログインプロンプトが表示されません。ただスローして、デバッガを突き刺した後、私はauth.username()が空の文字列を返すと判断しました。だから、私の推測では、何らかの理由で内部のデコレータが適用されていないため、ログインプロンプトが表示されません。

ここで何が起こっているのでしょうか?

私の最初の仮説は、管理デコレータの内部機能がis_adminチェックの後まで呼び出されていないため、これは簡単なバグであるということでした。次のようにだから私は、私は、関数を呼び出す---ので、おそらくチェックする前に--- auth.username()を利用可能にすることを解決しようとした:

def must_be_admin(f): 
    @wraps(f) 
    def wrapper(*args, **kwargs): 
     dummy_to_get_username = f(*args, **kwargs) 
     if dbops.is_admin(auth.username()): 
      return dummy_to_get_username 
     return "Not authorized." 
    return wrapper 

をしかし、それはちょうど同じ行動を起こしました。

私はthis prior SOから、ライブラリ作成者からこれを行うには、2つの別々のFlask-HTTPAuthオブジェクトを作成することをお勧めします。それは私がすることができます、問題ありません。しかし、デコレータがどのように動作しているかについての私の精神モデルは失敗しているので、私は作業したい機能を得ることとは無関係にこの問題を解決したいと思います...

答えて

1

デコレータを適用する正しい順序は、デコレータが何をしているのかを知らなくても、間違った順序でアプリケーションを正しく動作させることができます。

ビューファンクションが実行される前に何かを行うデコレータでは、通常、デコレータを実行する順序でデコレータを配置する必要があります。だから私はあなたのコードは、あなたが使用している場合、あなたが期待する何をすると思いフラスコ-HTTPAuthのlogin_required前に、あなたのmust_be_admin:このように

@core.route("/admin") 
@auth.login_required 
@must_be_admin 
def admin(): 
    return render_template("admin.html") 

は、資格情報が最初にチェックされ、存在しないか、または無効の場合 login_requiredは401エラーを返しますブラウザにログインすると、ログインプロンプトが表示されます。資格情報が有効であると判断された後でのみ、管理デコレータを評価します。

+0

ありがとうございました!すべてのフラスコの質問でここで活発に活動していることは素晴らしいことです。 –

関連する問題