Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/294.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 通过装饰器从令牌中提取用户id_Python_Rest_Flask - Fatal编程技术网

Python 通过装饰器从令牌中提取用户id

Python 通过装饰器从令牌中提取用户id,python,rest,flask,Python,Rest,Flask,我正在开发使用auth0进行身份验证和授权的flask RESTful应用程序。然后,我编写了一个decorator来验证令牌并从中提取用户id。我的目标是使用从令牌中提取的id在修饰函数中使用,如果来自令牌和来自URL参数的用户id不匹配,则引发异常。这是为了避免用户使用自己的令牌更改另一个用户的数据。我不确定这是否是RESTful应用程序的最佳实践,但在我的情况下似乎需要这样做 也就是说,我试图找出将用户id从令牌传递到修饰函数的最佳方法: 大概是这样的: def authorization

我正在开发使用auth0进行身份验证和授权的flask RESTful应用程序。然后,我编写了一个decorator来验证令牌并从中提取用户id。我的目标是使用从令牌中提取的id在修饰函数中使用,如果来自令牌和来自URL参数的用户id不匹配,则引发异常。这是为了避免用户使用自己的令牌更改另一个用户的数据。我不确定这是否是RESTful应用程序的最佳实践,但在我的情况下似乎需要这样做

也就是说,我试图找出将用户id从令牌传递到修饰函数的最佳方法:

大概是这样的:

def authorization():
    def inner(func):

        def wrapper(*args, **kwargs):
            try:
                """
                token validation stuff
                ...
                """
                wrapper.user_id = token_payload['user_id']

            except Exception:
                return {"success": False}, 500

            return func(*args, **kwargs)

        return wrapper
    return inner


@authorization()
@app.route('/test', methods=['GET'])
def some_function():
    return jsonify({
        'success': True,
        'user_id': some_function.user_id
    })
如您所见,我将user_id字段设置为包装器函数,这似乎不是最好的方法。对这种情况有什么不同的处理方法吗?也许是使用烧瓶资源

  • 您可以跳过装饰器中的一级包装,因为您没有给它任何参数
  • 此外,我只需将提取的id直接传递到包装函数中,而不是设置属性
  • 最后,您应该在最里面添加auth decorator,因为您要向Flask注册的是修饰函数
  • 额外:使用
    functools.wrapps
    更新已包装函数的签名,使内省和调试更容易
  • 因此:


    现在,您使用
    @authorized
    装饰的每个函数都需要将
    用户id
    作为其第一个参数,并且所有功能都应该按照您的预期工作。

    这是一个很好的观点。我真正的装饰器有参数,我考虑在kwargs中传递id,如果我这样做,装饰的每个函数都必须有**kwargs作为参数,即使我不需要该id该函数。@MatheusHernandes如果你有一些函数需要授权,但不需要
    用户id
    ,您也可以将其作为装饰器的参数。类似于
    @authorized(pass\u id=True)
    然后调用
    func(user\u id,…)
    或仅仅调用
    func(…)
    ,具体取决于此。可能是。。。我介于那个选择和另一个选择之间question@MatheusHernandes如果您希望以更结构化的方式执行此操作,您可以使用
    before\u request
    处理程序来处理授权内容,并将
    user\u id
    放入
    flask.g
    应用程序上下文命名空间。然后,您可以为需要授权的路由注册一个单独的
    蓝图
    ,该路由在请求前使用
    预处理器。
    
    from functools import wraps
    
    def authorized(func):
        @wraps(func)
        def wrapper(*args, **kw):
            try:
                # token stuff
                user_id = token_payload['user_id']
            except:
                return jsonify({"success": False}), 500
            return func(user_id, *args, **kw)
        return wrapper
    
    @app.route('/test', methods=['GET'])
    @authorized
    def some_function(user_id):
        return jsonify({
            'success': True,
            'user_id': user_id
        })