Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/google-app-engine/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 通过Flask中的装饰器进行身份验证_Python_Google App Engine_Flask_Python Decorators - Fatal编程技术网

Python 通过Flask中的装饰器进行身份验证

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

我有以下代码可以工作。它对给定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('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。是的,改变顺序已经奏效了。我想知道为什么?