如何动态装饰Flask规则?

时间:2017-01-17 21:19:30

标签: python google-app-engine flask decorator

我有一个包含大量自动定义规则的应用程序。在继续之前,我需要每个规则检查Bearer令牌。

我找到app.url_map.iter_rules()让我看到所有已定义的规则。我想要一种方法来重新定义每个规则以使用它的当前函数,但是用下面定义的authenticate_admin装饰器包装它。

from flask import Flask
from functools import wraps

app = Flask(__name__)

# Check that the request has the correct `bearer_token`.
def authenticate_admin(func):
    @wraps(func)
    def wrapped(*args, **kwargs):
        bearer_token = vault.get('secret/oauth')['bearer_token']
        expected = ("Bearer " + bearer_token)
        if expected != request.headers.get('Authorization'):
            return jsonify({'error': "Authorization token incorrect"}), 401

        return func(*args, **kwargs)
    return wrapped


# .... Define a bunch of routes (Elided) .... 

for rule in app.url_map.iter_rules():
    # NEXT LINE IS PSEUDOCODE; IT IS WHAT I WANT TO ACHIEVE
    rule.fx = authenticate_admin(rule.fx)

我想要的是,在执行上述for循环后,所有规则现在都要求您提供Bearer令牌。

1 个答案:

答案 0 :(得分:0)

最后,我最后添加了以下davidism的建议,并使authenticate成为由所有端点运行的函数。我添加了 NOT 要求身份验证的端点白名单。

from flask import request
import vault

app = Flask(__name__)

# .... Define a bunch of routes (Elided) .... 


WHITELIST_POST = ['/post1', '/post2', '/post3']


WHITELIST_GET = ['/', '/get1', '/get2']


def authenticate():
    if request.method == "GET" and request.url_rule.rule in WHITELIST_GET:
        return
    if request.method == "POST" and request.url_rule.rule in WHITELIST_POST:
        return
    bearer_token = vault.get('secret/oauth')['bearer_token']
    expected = ("Bearer " + bearer_token)
    if expected != request.headers.get('Authorization'):
        abort(401)

app.before_request(authenticate)

另一方面,我的老板更喜欢这个。这意味着我们默认在服务器上创建的任何端点都需要一个承载令牌。在过去,我们忘记了为某些端点要求持票人令牌。现在它选择退出而不是选择加入。