向Flask Restx添加身份验证装饰器

时间:2020-07-31 08:17:55

标签: python flask flask-restplus flask-restx

我有一个使用flask-restxflask-login的Flask应用程序。我希望默认情况下所有路由都需要登录,并显式定义不需要身份验证的公共路由。我已经按照这个问题给出的示例开始使用装饰器:

Best way to make Flask-Login's login_required the default

它适用于功能端点,不适用于restx资源端点。

我尝试将函数添加为装饰器,并使用method_decorators字段。例如:

def public_route(decorated_function):
    """
    This is a decorator to specify public endpoints in our flask routes
    :param decorated_function:
    :return:
    """
    decorated_function.is_public = True
    return decorated_function


class HelloWorld(ConfigurableResource):

    method_decorators = {"get": [public_route]}

    @public_route
    @api.doc('Welcome message')
    def get(self):
        return {'hello': 'world'}

此测试通过:

def test_hello_world_is_public():
    api = Namespace('health', description='Health related operations')
    hello = HelloWorld(api, config=None, logger=None)
    is_public_endpoint = getattr(hello.get, 'is_public', False)
    assert is_public_endpoint

我的挑战是我无法在身份验证逻辑中看到如何访问此属性:


    @app.before_request
    def check_route_access():
        """
        This function decides whethere access should be granted to an endpoint.
        This function runs before all requests.
        :return:
        """
        is_public_endpoint = getattr(app.view_functions[request.endpoint], 'is_public', False)

        if person_authorized_for_path(current_user, request.path, is_public_endpoint):
            return
        # Otherwise access not granted
        return redirect(url_for("auth.index"))

这适用于普通函数端点,但不适用于restx资源。

我知道restx将我的资源类包装在一个函数中,以便flask可以进行分派,但是我不知道如何从这里访问装饰器。所以我有一些问题:

  • 是否可以从view_function到达装饰器?
  • 是否可以知道端点是restx资源还是普通的rest函数?
  • 是否有更好的方法来完成我要达到的目标?

2 个答案:

答案 0 :(得分:2)

是否可以从view_function到达装饰器?

好吧...这是可能的,但我不建议这样做。这是一个example

是否可以知道端点是restx资源还是 简单的休息功能?

您可能可以检查该功能,并弄清它是否来自restx,也许是在查看__qualname__,但是话又说回来,我将不推荐它。

是否有更好的方法来完成我要达到的目标?

我将采用以下解决方案之一:

  • 显式装饰确实需要身份验证的view_funcs和资源,而不是相反地装饰
  • 使用公共before_request装饰器为公用端点创建一个蓝图,为受保护端点创建一个蓝图

答案 1 :(得分:1)

基于thisthismethod_decorators变量应该是函数列表,因此您应该像这样使用它:

def _perform_auth(method):
    is_public_endpoint = getattr(method, 'is_public', False)
    # place the validation here

class Resource(flask_restx.Resource):
    method_decorators = [_perform_auth]
相关问题