我目前正在重構一個我兩年前寫過的Flask應用程序,並且我懷疑已經完成了一些並不像使用庫時那樣優雅和乾淨的事情。因此,我會問有關如何在現狀提高了一些建議:Flask中的自定義身份驗證和參數檢查
- 該應用程序通過形式
/<category>/<endpoint>
其中<category>
是10個不同類別之一的路線提供了一些API,每個端點的可到達。 - 對於每個
<category>
我創建一個獨特的Python模塊<category>.py
,把它放在一個api/
子目錄和不同flask.Blueprint
(實際上是一個子類物,見下文中的),並註冊與所述主app = Flask(__name__)
。 - 每個模塊
<category>.py
包含多個函數,用作相應類別的端點,並且每個函數都使用路由裝飾器進行修飾。
到目前爲止好。
每個端點函數都接受許多參數,這些參數可以作爲GET請求的參數傳遞,也可以作爲POST請求的JSON有效內容中的parameter
字段的一部分傳遞。因此,在調用相應的端點功能之前,檢查是否提供了正確名稱的正確數量的參數。
此外,應用程序需要檢查是否允許客戶端調用某個功能。爲此,讀取由Web服務器(在我的情況下爲FCGI上的lighttpd)設置的環境變量SSL_CLIENT_CERT
,並將其指紋與某些內部權限文件進行比較。
因爲我不知道在哪裏把邏輯做到上面我分類flask.Blueprint
和寫我自己的(修改)route
修飾器(custom_route
)。這個裝飾器現在返回一個自定義的錯誤響應(flask.Response
對象)或一個自定義的成功響應(從而使用從客戶端傳遞的參數調用端點函數)。
所以一個模塊category_xy.py
看起來是這樣的:
category_xy = CustomBlueprint('category_xy', __name__)
@category_xy.custom_route('/category_xy/some_endpoint',
auth_required=True,
methods=['GET', 'POST'])
def some_endpoint(foo, bar):
# do stuff
return '123'
在一個單獨的文件中定義爲(部分pseudoish代碼)CustomBlueprint
:
from flask import Blueprint, Response, g, request
from functools import wraps
class CustomBlueprint(Blueprint):
def custom_route(self, rule, **options):
def decorator(f):
# don't pass the custom parameter 'auth_required' on to
# self.route
modified_options = dict(options)
if 'auth_required' in modified_options:
del modified_options['auth_required']
@self.route(rule, **modified_options)
@wraps(f)
def wrapper():
# do some authentication checks...
if not authenticiated():
return Response(...)
# check if correct paramters have been passed
if not correct_paramters():
return Response(...)
# extract parameter values from either GET or POST request
arg_values = get_arg_values(request)
# call the decorated function with these parameters
result = f(*arg_values)
return Response(result, ...)
return wrapper
return decorator
這工作,但給人的感覺並不乾淨我認爲應該有一個更好更乾淨的方式來做到這一點。把所有這些邏輯放在一個自定義的裝飾器中感覺是錯誤的。
有人對Flask有更多的經驗可以提供一些想法和/或最佳實踐嗎?
我想你的類別有一些共同之處:類似的端點名稱,授權機制,驗證函數。那就對了? –
是的!每個端點功能都會觸發服務器上的某些操作。一個類別內的所有操作都有些相關,並且通常也有類似的端點名稱。 –