通过 Flask 中的装饰器进行身份验证
Authentication via decorators in Flask
我有以下有效的代码。它为给定的 url 验证管理员用户。如果用户不是管理员,那么它 returns 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('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'))
上面的代码有效,我想用它做一个装饰器。所以我写了以下内容。但是它不起作用,因为
的值
user = None
片段 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_admin
的 return 值作为 authenticate_and_call
函数,而不是它的调用 authenticate_and_call()
:
return authenticate_and_call
装饰器的顺序很重要。如果代码的结构与问题中的相同,则 admin_routes
装饰 basic
和 returns 一个函数(funcA
)。该函数 funcA
然后由 authenticate_admin
修饰,其中 returns funcB
。所以实际分配给路由回调的函数是给 admin_routes
的函数,它是 basic
而不是 basic 的装饰版本(funcA
,或 funcB
) .所以你的 funcB
永远不会被调用,因此你的身份验证逻辑不会被执行
当您将订单更改为
@admin_routes.route('/xxxx')
@authenticate_admin
def basic():
...
这里 authenticate_admin
returns 修饰函数 funcA
然后由 admin_routes
修饰。因此,分配为回调的函数是 funcA
而不是 basic
。因此,当您转到 /xxxx
、funcA
并执行您的身份验证逻辑时。
错误似乎是当您在未登录的情况下导航到 /xxxx
时,它会尝试 render_template
和 user=None
并且很可能您的模板使用 user.nickname
这是一个 AttributeError
.
我有以下有效的代码。它为给定的 url 验证管理员用户。如果用户不是管理员,那么它 returns 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('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'))
上面的代码有效,我想用它做一个装饰器。所以我写了以下内容。但是它不起作用,因为
的值user = None
片段 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_admin
的 return 值作为 authenticate_and_call
函数,而不是它的调用 authenticate_and_call()
:
return authenticate_and_call
装饰器的顺序很重要。如果代码的结构与问题中的相同,则 admin_routes
装饰 basic
和 returns 一个函数(funcA
)。该函数 funcA
然后由 authenticate_admin
修饰,其中 returns funcB
。所以实际分配给路由回调的函数是给 admin_routes
的函数,它是 basic
而不是 basic 的装饰版本(funcA
,或 funcB
) .所以你的 funcB
永远不会被调用,因此你的身份验证逻辑不会被执行
当您将订单更改为
@admin_routes.route('/xxxx')
@authenticate_admin
def basic():
...
这里 authenticate_admin
returns 修饰函数 funcA
然后由 admin_routes
修饰。因此,分配为回调的函数是 funcA
而不是 basic
。因此,当您转到 /xxxx
、funcA
并执行您的身份验证逻辑时。
错误似乎是当您在未登录的情况下导航到 /xxxx
时,它会尝试 render_template
和 user=None
并且很可能您的模板使用 user.nickname
这是一个 AttributeError
.