簡體   English   中英

如何使用參數在Flask中創建python裝飾器函數(用於授權)

[英]How to make a python decorator function in Flask with arguments (for authorization)

我在燒瓶登錄中使用了一個燒瓶片段來檢查用戶是否已登錄:

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資源。

如果logged_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視圖可以從路徑中的變量訪問的熱狗參數。 我的希望是......

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

一切都適用於我當前的authorizeowner(熱狗)功能,但是將它作為我的路線頂部的包裝器而不是作為路線內的第一行,這似乎更清晰。

其他一些說明:

  • 我知道Flask-Security和Flask-Principal可以為我管理授權。 不幸的是,我使用的是不受支持的數據庫后端,我無法使用這些擴展。 所以,我不得不在沒有他們的情況下進行身份驗證。
  • 如果你看到以這種方式授權的任何明顯漏洞,請告訴我!

這是怎么做的:

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

當decorator接受參數時,它不是真正的裝飾器,而是返回真正裝飾器的工廠函數。

但如果我是你,我會使用Flask-Login進行身份驗證,並使用自定義裝飾器和函數來擴充它以處理授權。

我看了看Flask-Principal,但發現它的味道過於復雜。 沒有檢查Flask-Security,但我相信它使用Flask-Principal進行授權。 總的來說,我認為使用一些自定義代碼的Flask-Login足夠大部分時間。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM