我一直在从瓶子到烧瓶的转变。我是那种喜欢自己写代码的人,而不是从网上下载包,如果我需要的代码是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-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:这是从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.'