Добавление декораторов аутентификации в flask restx

У меня есть приложение Flask, использующее flask-restx и flask-login. Я бы хотел, чтобы все маршруты по умолчанию требовали входа в систему и явно определяли общедоступные маршруты, не требующие аутентификации. Я начал использовать декораторы, следуя примеру, приведенному в этом вопросе:

Он работает для конечных точек функций, но не для конечных точек 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 оборачивает мой класс ресурсов в функцию, чтобы фляга могла выполнять отправку, но я не могу понять, как получить отсюда доступ к декоратору. Итак, у меня есть несколько вопросов:

  • Можно ли добраться до декоратора из view_function?
  • Можно ли узнать, является ли конечная точка ресурсом restx или простой функцией отдыха?
  • Есть ли лучший способ сделать то, что я пытаюсь достичь?

person mikelong    schedule 31.07.2020    source источник


Ответы (2)


На основе this и this, method_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]
person Andrey Kurilin    schedule 21.08.2020
comment
Есть ли способ применить этот method_decorator глобально, чтобы мне не приходилось размещать его на каждом ресурсе? Я попытался добавить функцию perform_auth к decorators аргументам Api и Namespace, но, похоже, она не работает - person Santiago Alvarez; 22.07.2021

Можно ли добраться до декоратора из view_function?

Что ж ... это возможно, но я бы не рекомендовал это. Вот пример

Можно ли узнать, является ли конечная точка ресурсом restx или простой функцией отдыха?

Вы, вероятно, сможете проверить функцию и выяснить, не из restx, возможно, глядя на __qualname__, но опять же, я бы не рекомендовал это.

Есть ли лучший способ сделать то, что я пытаюсь достичь?

Я бы выбрал одно из этих решений:

  • Явно украшайте view_funcs и ресурсы, требующие аутентификации, а не наоборот
  • Создайте схему общедоступных конечных точек, схему защищенных конечных точек с before_request декоратором для авторизации.
person Gabriel Cappelli    schedule 07.08.2020