Flask:如何为所有方法注册一个封装器?

问题描述 投票:0回答:1

我一直在从瓶子到烧瓶的转变。我是那种喜欢自己写代码的人,而不是从网上下载包,如果我需要的代码是20行或更少。比如说支持 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)

上面的代码让我对所有的方法都完全支持基本的认证协议,除非明确地用了 @allow_anonymous 包装纸。我只是一个flask的初学者。我很难在flask中完成上面的瓶子兼容代码,而不增加对更多python包的依赖,也不需要过多的锅炉模板。在flask中是如何直接清晰地处理的?

flask bottle
1个回答
2
投票

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

我认为你将需要玩一些 before_request 游戏(不是很美),或者叫烧瓶的。add_url_rule 为每个api端点配备一个装饰的方法(或者有一个 route 你自己的装饰者,将做到这一点)。) 的 add_url_rule 得到一个视图函数,它通常是你的api端点处理程序,但在你的情况下,将是一个封装的方法,其方式很像你在帖子中给出的方法(auth_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))

当然,可以(也应该)通过以下方式来进一步加强 蓝图,等等。


1
投票

注#1:这是从SO中的单独答案中摘录出来的。

注2:这不使用蓝图。再次强调,我是flask的新手,我很感激蓝图会帮助应用规模化,但一步一步......

def allow_anonymous(decorated_function):
    decorated_function.is_public = True
    return decorated_function

@app.before_request
def auth_middleware():
    fn = app.view_functions[request.endpoint]
    if hasattr(fn, 'allow_anonymous') and fn.allow_anonymous:
        # anonymous permitted
        return
    elif my_custom_authentication():
        # anonymous not permitted authentication succeeded
        return
    else:
        # anonymous not permitted authentication failed
        err_response = make_response(text, 401)
        err_response.headers['WWW-Authenticate'] = 'Basic realm="%s"' % realm
        return err_response

@app.route('/public_thing')
@allow_anonymous
def public_thing():
   return 'yo'

@app.route('/regular_thing')
def regular_thing():
   return 'if you can read this youre authenticated.'

© www.soinside.com 2019 - 2024. All rights reserved.