为 Flask 创建身份验证装饰器的问题

Posted

技术标签:

【中文标题】为 Flask 创建身份验证装饰器的问题【英文标题】:Problems with the creation of a authentication decorator for Flask 【发布时间】:2019-07-02 06:55:04 【问题描述】:

我正在尝试为我的所有 Flask app.routes 设置身份验证装饰器。每次调用与路由关联的函数时,我都会检查请求是否传递了正确的键。

我已经创建了一个装饰器(这可能是错误的)来做到这一点。首先它说它没有配置返回值,我后来修复了它。当我尝试再次运行它时,错误提示:

"TypeError: unregisterApi() 接受 0 个位置参数,但给出了 2 个 视图函数未返回有效响应。返回类型必须是字符串、元组、响应实例或 WSGI 可调用的,但它是一个函数。 ”。

我确定问题出在我的装饰器上,但我不知道如何解决。

以下是装饰器和被装饰函数的代码:

装饰者:

def requestAuth(func):
   def funcWrapper():
       data = request.get_json(force=True)
       apiAddr = request.remote_addr
       apiKey = data["API Register Key"]

       conn = sqlite3.connect("database/controllerConfiguration.db")
       cursor = conn.cursor()
       cursor.execute('select apikey from SystemAPI where apihost  = \"0\";'.format(apiAddr))
       result = cursor.fetchall()
       if result[0][0] != apiKey:
           return "ERROR - Authentication with the controller failed",400
       elif result[0][0] == apiKey:
           return func
   return funcWrapper

它修饰的路由关联函数:

@app.route('/unregister',methods=['POST'])
@requestAuth
def unregisterApi():
   data = request.get_json(force=True)
   apiKey = data["API Register Key"]
   apiAddr = request.remote_addr

   conn = sqlite3.connect('database/controllerConfiguration.db')
   cursor = conn.cursor()
   cursor.execute('delete from SystemAPI where apikey = \"\";'.format(apiKey))
   conn.commit()
   conn.close()

   return jsonify("Response":"Success")

我希望达到的是:

每次调用路由 (/unregister,/register,...) 函数时,@requestAuth 装饰器都会检查是否传递了正确的键,如果是,它将恢复到路由函数并执行它应该执行的操作,如果键不匹配它会简单地返回错误字符串以及相关的状态码(string: "ERROR - Authentication with the controller failed", Status code: 400).

【问题讨论】:

【参考方案1】:

问题在于funcWrapper 中的elif 语句:

elif result[0][0] == apiKey:
   return func

func 是一个可调用对象,即由requestAuth 包装的原始函数,在本例中为unregisterApi。相反,调用func 以返回有效类型而不是对象实例本身:

elif result[0][0] == apiKey:
   return func()

另外,请记住,如果 ifelif 语句都失败,None 将由 funcWrapper 返回,再次引发原始错误。因此,您可能需要重新考虑您希望如何处理该特定情况。

【讨论】:

以上是关于为 Flask 创建身份验证装饰器的问题的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Flask 中实现登录所需的装饰器

测试 Flask 登录和身份验证?

Flask-RESTful中装饰器的使用

如何实现 REST API 的身份验证?

如何实现 REST API 的身份验证?

使用 flask-jwt-extended + ariadne (graphql) + react 设置身份验证/授权