25

ユーザーがログインしていることを確認するフラスコログインにフラスコスニペットを使用しました。

from functools import wraps

def logged_in(f):
    @wraps(f)
    def decorated_function(*args, **kwargs):
        if session.get('logged_in') is not None:
            return f(*args, **kwargs)
        else:
            flash('Please log in first.', 'error')
            return redirect(url_for('login'))
    return decorated_function

そして、私はビューを次のように飾ります:

@app.route('/secrets', methods=['GET', 'POST'])
@logged_in
def secrets():
    error = None

承認についても同様のことをしたいと思います。現在、ユーザーがリソース、たとえばリソースを所有していることを確認するためのビューがたくさんありますhotdogs

login_in ユーザーがその特定のホットドッグの所有者である場合、そのユーザーは自分のホットドッグを編集および管理できます。そうでない場合は、許可されていない画面に追い出します。

@app.route('/<hotdog>/addmustard/',methods=["GET"])
@logged_in
def addmustard(hotdog):
    if not (authorizeowner(hotdog)):
        return redirect(url_for('unauthorized'))
    do_stuff()

authorizeowner()ホットドッグを入力として取り、記録されたホットドッグ所有者がセッション変数にリストされている所有者名と一致することを確認します。

ログインしたものと同様の owns_hotdog ラッパー/デコレーター関数を作成しようとしましたが、引数を受け入れないと不平を言いました。どうすれば同様のことを達成できますか? 何かのようなもの...

def owns_hotdog(f):
    @wraps(f)
    def decorated_function(*args, **kwargs):
        if not authorizeowner(hotdog):
            return f(*args, **kwargs)
        else:
            flash('Please log in first.', 'error')
            return redirect(url_for('login'))
    return decorated_function

エラー メッセージから、デコレーターは、Flask ビューがルート内の変数からアクセスできる hotdog 引数を受け取っていないようです。私の希望は次のようなものです...

@app.route('/<hotdog>/addmustard/',methods=["GET"])
@logged_in
@owns_hotdog(hotdog)
def addmustard(hotdog):
    do_stuff()

すべてが現在の authorizeowner(hotdog) 関数で機能しますが、これをルート内の最初の行としてではなく、ルートの上にラッパーとして配置する方がきれいに見えます。

その他の注意事項:

  • Flask-Security と Flask-Principal が私の代わりに承認を管理できることを知っています。残念ながら、サポートされていないデータベース バックエンドを使用しているため、これらの拡張機能を使用できません。そのため、それらなしで認証を行う必要があります。
  • この方法で承認を行う際に明らかな穴がある場合は、お知らせください。
4

1 に答える 1

24

方法は次のとおりです。

from functools import update_wrapper

def owns_hotdog(hotdog):
    def decorator(fn):
        def wrapped_function(*args, **kwargs):
            # First check if user is authenticated.
            if not logged_in():
                return redirect(url_for('login'))
            # For authorization error it is better to return status code 403
            # and handle it in errorhandler separately, because the user could
            # be already authenticated, but lack the privileges.
            if not authorizeowner(hotdog):
                abort(403)
            return fn(*args, **kwargs)
        return update_wrapper(wrapped_function, fn)
    return decorator

@app.errorhandler(403)
def forbidden_403(exception):
    return 'No hotdogs for you!', 403

デコレータが引数を取る場合、それは実際にはデコレータではなく、実際のデコレータ返すファクトリ関数です。

しかし、もし私があなたなら、Flask-Login を認証に使用し、独自のカスタム デコレーターと関数を追加して承認を処理します。

Flask-Principal を調べましたが、私の好みでは複雑すぎることがわかりました。Flask-Security はチェックしていませんが、認証に Flask-Principal を使用していると思います。全体として、ほとんどの場合、いくつかのカスタム コードを使用した Flask-Login で十分だと思います。

于 2012-12-16T09:56:24.700 に答える