[英]Authentication via decorators in Flask
I have the following code which works. 我有以下有效的代码。 It authenticates admin users for the given url.
它验证给定URL的管理员用户。 If the users is not Admin then it returns a 401.
如果用户不是管理员,则返回401。
Snippet 1: 片段1:
__author__ = 'xxxx'
from flask import render_template, url_for
from flask import Blueprint, redirect, request, session, abort
from google.appengine.api import users
admin_routes = Blueprint('admin_routes', __name__)
@admin_routes.route('/xxxx')
def basic():
user = users.get_current_user()
if user:
if not users.is_current_user_admin():
return abort(401)
else:
return render_template('xxx/xxxx.html', user=user,
logout=users.create_logout_url('/'))
else:
return redirect(users.create_login_url('/xxxx'))
The above code works and I wanted to make a decorator out of it. 上面的代码有效,我想用它做一个装饰器。 So I wrote the following.
所以我写了以下内容。 However it does not work, as the value of
但是,它不起作用,因为
user = None
用户=无
Snippet 2: 片段2:
from google.appengine.api import users
from flask import abort, redirect
def authenticate_admin(func):
def authenticate_and_call(*args, **kwargs):
user = users.get_current_user()
if user is None:
print("Redirecting user to login page")
return redirect(users.create_login_url('xxxxx/xxxx'), 401)
else:
if not users.is_current_user_admin():
return abort, 401
return func(*args, **kwargs)
return authenticate_and_call()
How would I write the decorator so it does what the Snippet 1 does. 我将如何编写装饰器,使其完成代码段1的工作。 End result should be something like so.
最终结果应该是这样的。
__author__ = 'xxxxxx'
from flask import render_template, url_for
from flask import Blueprint, redirect, request, session, abort
from google.appengine.api import users
admin_routes = Blueprint('admin_routes', __name__)
@authenticate_admin
@admin_routes.route('/xxxx')
def basic():
return render_template('xxx/xxxx.html', user=user,
logout=users.create_logout_url('/'))
The exception i get for the above code is 我上面的代码得到的异常是
UndefinedError: 'None' has no attribute 'nickname'
The order of decorators matter. 装饰者的顺序很重要。 If the code is structured as in the question,
admin_routes
decorates basic
and returns a function ( funcA
). 如果代码按照问题的结构进行构造,则
admin_routes
装饰basic
并返回一个函数( funcA
)。 That function, funcA
, is then decorated by authenticate_admin
which returns funcB
. 然后,该函数
funcA
由authenticate_admin
装饰,该函数返回funcB
。 So the function that actually is assigned as callback for the route is the function given to admin_routes
which is basic
and not the decorated version of basic ( funcA
, or funcB
). 因此,实际上分配给路由的回调的函数是给
admin_routes
的函数,它是basic
函数,而不是basic
的修饰版本( funcA
或funcB
)。 So your funcB
is never called and hence your authentication logic is not executed 因此,您的
funcB
不会被调用,因此不会执行身份验证逻辑
When you change the order to 当您将订单更改为
@admin_routes.route('/xxxx')
@authenticate_admin
def basic():
...
Here authenticate_admin
returns the decorated function funcA
which is then decorated by admin_routes
. 这里
authenticate_admin
返回修饰的函数funcA
,然后由admin_routes
修饰。 So the function assigned as a callback is funcA
not basic
. 因此,分配为回调的
funcA
不是funcA
basic
。 So when you go to /xxxx
, funcA
and your authentication logic is executed. 因此,当您转到
/xxxx
, funcA
就会执行身份验证逻辑。
The error seems to be when you navigate to /xxxx
when you are not logged in, it tries to render_template
with user=None
and most likely your template uses user.nickname
which is an AttributeError
. 错误似乎是当您未登录时导航到
/xxxx
时,它尝试使用user=None
user.nickname
render_template
,并且很可能您的模板使用user.nickname
,这是AttributeError
。
我认为您需要authenticate_admin
的返回值是authenticate_and_call
函数,而不是其调用authenticate_and_call()
:
return authenticate_and_call
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.