Flask:如何向所有方法注册包装器

nac*_*man 11 bottle flask

我一直在从瓶子转移到烧瓶。如果我需要的代码不超过 20 行,我是那种更喜欢编写自己的代码而不是从 Internet 下载软件包的人。以支持Basic身份验证协议为例。在瓶子里我可以写:

def allow_anonymous():
    """assign a _allow_anonymous flag to functions not requiring authentication"""
    def wrapper(fn):
        fn._allow_anonymous = True
        return fn
    return wrapper


def auth_middleware(fn):
    """perform authentication (pre-req)"""
    def wrapper(*a, **ka):
        # if the allow_anonymous annotation is set then bypass this auth
        if hasattr(fn, '_allow_anonymous') and fn._allow_anonymous:
            return fn(*a, **ka)
        user, password = request.auth or (None, None)
        if user is None or not check(user, password):
            err = HTTPError(401, text)
            err.add_header('WWW-Authenticate', 'Basic realm="%s"' % realm)
            return err
        return fn(*a, **ka)
    return wrapper

...

app = Bottle()
app.install(middleware.auth_middleware)
Run Code Online (Sandbox Code Playgroud)

上面的代码让我完全支持所有方法的基本身份验证协议,除非用@allow_anonymous包装器显式装饰。我只是一个烧瓶的初学者。我很难在烧瓶中完成上面与瓶子兼容的代码而不添加对更多 python 包或过多样板的依赖。这是如何在烧瓶中直接清晰地处理的?

MrM*_*ter 4

如果你愿意的话,你绝对可以自己使用flask-httpauth的一些功能:-P

我认为你需要玩一些游戏(不是很漂亮),或者用每个 api 端点的装饰方法调用before_requestFlask (或者有一个你自己的装饰器来执行此操作)。获取一个视图函数,该函数通常是您的 api 端点处理程序,但在您的情况下,它将是一个包装方法,其方式与您在帖子 ( ) 中给出的方式非常相似。add_url_rulerouteadd_url_ruleauth_middleware

其要点:

from flask import Flask, make_response, request

app = Flask(__name__)

def view_wrapper(fn):
    """
    Create a wrapped view function that checks user authorization
    """
    def protected_view(*a, **ka):
        # if the allow_anonymous annotation is set then bypass this auth
        if hasattr(fn, '_allow_anonymous') and fn._allow_anonymous:
            return fn(*a, **ka)
        # consult werkzeug's authorization mixin
        user, password = (request.authorization.username, request.authorization.password) if request.authorization else (None, None)
        if user is None or not check(user, password):
            err_response = make_response(text, 401)
            err_response.headers['WWW-Authenticate'] = 'Basic realm="%s"' % realm
            return err_response
        return fn(*a, **ka)

    return protected_view


# An endpoint
def hello():
    return 'hello there'

app.add_url_rule('/', 'hello', view_wrapper(hello))
Run Code Online (Sandbox Code Playgroud)

当然,这可以(并且应该)通过蓝图等进一步增强。