Python 通过Flask中的装饰器进行身份验证
我有以下代码可以工作。它对给定url的管理员用户进行身份验证。如果用户不是管理员,则返回401 片段1:Python 通过Flask中的装饰器进行身份验证,python,google-app-engine,flask,python-decorators,Python,Google App Engine,Flask,Python Decorators,我有以下代码可以工作。它对给定url的管理员用户进行身份验证。如果用户不是管理员,则返回401 片段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('adm
__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'))
上面的代码很有效,我想用它做一个装饰器。所以我写了以下内容。但是它不起作用,因为
用户=无
片段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()
我将如何编写装饰器,使其实现代码片段1的功能。最终结果应该是这样的
__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('/'))
上述代码的例外情况是
UndefinedError: 'None' has no attribute 'nickname'
我认为您需要
authenticate\u admin
的返回值作为authenticate\u和\u call
函数,而不是它的调用authenticate\u和\u call()
:
我认为您需要
authenticate\u admin
的返回值作为authenticate\u和\u call
函数,而不是它的调用authenticate\u和\u call()
:
装饰师的顺序很重要。如果代码的结构如问题所述,
admin\u路由
装饰basic
,并返回一个函数(funcA
)。然后由authenticate\u admin
修饰该函数funcA
,该函数返回funcB
。因此,实际分配为路由回调的函数是提供给admin\u routes
的函数,它是basic
,而不是basic的修饰版本(funcA
,或funcB
)。因此,永远不会调用funcB
,因此不会执行身份验证逻辑
当您将订单更改为
@admin_routes.route('/xxxx')
@authenticate_admin
def basic():
...
此处authenticate\u admin
返回修饰后的函数funcA
,该函数随后由admin\u路由
修饰。因此,分配为回调的函数是funcA
而不是basic
。因此,当您转到/xxxx
,funcA
时,将执行您的身份验证逻辑
错误似乎是当您导航到
/xxxx
时,当您未登录时,它试图使用user=None
呈现您的模板,并且您的模板很可能使用user.昵称
,这是一个属性错误装饰者的顺序很重要。如果代码的结构如问题所述,admin\u路由
装饰basic
,并返回一个函数(funcA
)。然后由authenticate\u admin
修饰该函数funcA
,该函数返回funcB
。因此,实际分配为路由回调的函数是提供给admin\u routes
的函数,它是basic
,而不是basic的修饰版本(funcA
,或funcB
)。因此,永远不会调用funcB
,因此不会执行身份验证逻辑
当您将订单更改为
@admin_routes.route('/xxxx')
@authenticate_admin
def basic():
...
此处authenticate\u admin
返回修饰后的函数funcA
,该函数随后由admin\u路由
修饰。因此,分配为回调的函数是funcA
而不是basic
。因此,当您转到/xxxx
,funcA
时,将执行您的身份验证逻辑
错误似乎是在您未登录时导航到/xxxx
,它尝试用user=None
呈现模板user,很可能你的模板使用了user。昵称是一个AttributeError
尝试过了我仍然得到一个异常UndelineError:“None”没有属性“昵称”我不熟悉,所以我不确定这一点:我的装饰程序也不会在重定向
和func
调用的等价项前面使用return
。尝试过了,我仍然得到了一个异常UndeinederRor:“None”没有属性“昵称”,我不熟悉,因此,我不确定这一点:我的装饰器也不会在重定向
和func
调用的等价项前面使用return
,您可以尝试更改装饰器的顺序吗?您要用@admin\u routes
修饰的函数是已由authenticate\u admin
修饰的函数,对吗?它感觉像是@admin_routes
将路由分配给函数basic
,当您路由到/xxxx
时,它使用函数basic
进行路由,而您的呈现模板使用用户。昵称其中您的用户为无@hgwells。是的,改变顺序已经奏效了。我想知道为什么?你能试着改变一下装饰师的顺序吗?您要用@admin\u routes
修饰的函数是已由authenticate\u admin
修饰的函数,对吗?它感觉像是@admin_routes
将路由分配给函数basic
,当您路由到/xxxx
时,它使用函数basic
进行路由,而您的呈现模板使用用户。昵称其中您的用户为无@hgwells。是的,改变顺序已经奏效了。我想知道为什么?