Аутентификация клиента Python с декораторами

Я хочу создать клиент Python поверх REST API, который использует аутентификацию с помощью api_token. Следовательно, для всех вызовов API требуется api_token. Поскольку довольно некрасиво добавлять поле

'token=...'

например

a = f1(5, token='token')
b = f2(6, 12, token='token')
c = f3(2, 'a', token='token')

где внутренне f1 и f2 делегируют REST API

к каждому вызову функции. Я хотел бы иметь что-то вроде:

auth = authenticate('token')

a = f1(5)
b = f2(6, 12,)
c = f3(2, 'a')

Что я могу сделать, так это создать класс и сделать все функции-члены функциями. Следовательно, у нас было бы:

auth = calculator('token')
a = auth.f1(5)
b = auth.f2(6, 12,)
c = auth.f3(2, 'a')

но это тоже было бы несколько некрасиво. Я пытаюсь заставить это работать с декораторами, но пока безрезультатно.

class authenticate:
   def __init__(self, token):
       self.token = token

   def __call__(self, func):
       def functor(*args, **kwargs):
           return func(*args, **kwargs, key=self.authentication)
       return functor 

@authenticate
def f1(a, key):
    data = a
    result = requests.get(1, data, key)
    return result

Однако, похоже, это никуда не денется. Мне также интересно, может ли это вообще работать, поскольку декораторы выполняются во время импорта, а токен добавляется во время выполнения.

Любые предложения о том, как сделать эту работу, или кто-нибудь знает, есть ли для этого другой стандартный шаблон?

Вы хотите использовать токен для вызова методов класса? Как вы планируете его подтверждать?

Olvin Roght 22.05.2019 16:41

Как вы думаете, почему создание f1 et al. методы одного класса уродливы?

chepner 22.05.2019 16:41

Я согласен с @chepner: класс, вероятно, был бы самым чистым подходом для случая, описанного в вопросе.

Ralf 22.05.2019 16:43

@OlvinRoght Я хочу вызывать функции, которые выполняют вызов REST API. Я пропустил это, но есть также этап отображения аргументов python в json до вызова и из json в типы python после вызова.

Mike 22.05.2019 16:53

@chepner и Ральф. В идеале я хочу использовать удаленные функции, как если бы я использовал локальные функции, а не через выделенный класс аутентификации. Может быть, это невозможно, я не знаю, и это лучшее, что можно сделать.

Mike 22.05.2019 16:56

Что такое удаленная функция? f1 и др. необходимо получить ключ из где-то либо в качестве аргумента, либо в качестве глобальной переменной. Класс предоставляет третий вариант, когда ключ прикрепляется к экземпляру, вызывающему метод.

chepner 22.05.2019 17:00

идея заключалась бы в том, чтобы передать токен декоратору, а затем декоратор добавил бы его к функциям, таким как f1. Я сомневаюсь, что это сработает, поскольку декоратор запускается во время импорта и хочет добавить токен во время выполнения. Мой вопрос больше. Было ли это сделано, и каково типичное решение? Если это классовый подход, то мы используем классовый подход.

Mike 22.05.2019 17:10

@ Майк, ты используешь токен заголовка Authorisation: Bearer ... или?

Jon Clements 22.05.2019 17:13

@JonClements Это будет токен JWT

Mike 22.05.2019 22:08

эээ... может быть, редактировать ваш вопрос похож на этот? Есть также расширение библиотеки для requests, возможно, называемое requests_jwt или что-то в этом роде...?

Jon Clements 23.05.2019 00:07
Анализ настроения постов в Twitter с помощью Python, Tweepy и Flair
Анализ настроения постов в Twitter с помощью Python, Tweepy и Flair
Анализ настроения текстовых сообщений может быть настолько сложным или простым, насколько вы его сделаете. Как и в любом ML-проекте, вы можете выбрать...
7 лайфхаков для начинающих Python-программистов
7 лайфхаков для начинающих Python-программистов
В этой статье мы расскажем о хитростях и советах по Python, которые должны быть известны разработчику Python.
Установка Apache Cassandra на Mac OS
Установка Apache Cassandra на Mac OS
Это краткое руководство по установке Apache Cassandra.
Сертификатная программа "Кванты Python": Бэктестер ансамблевых методов на основе ООП
Сертификатная программа "Кванты Python": Бэктестер ансамблевых методов на основе ООП
В одном из недавних постов я рассказал о том, как я использую навыки количественных исследований, которые я совершенствую в рамках программы TPQ...
Создание персонального файлового хранилища
Создание персонального файлового хранилища
Вы когда-нибудь хотели поделиться с кем-то файлом, но он содержал конфиденциальную информацию? Многие думают, что электронная почта безопасна, но это...
Создание приборной панели для анализа данных на GCP - часть I
Создание приборной панели для анализа данных на GCP - часть I
Недавно я столкнулся с интересной бизнес-задачей - визуализацией сбоев в цепочке поставок лекарств, которую могут просматривать врачи и...
0
10
1 066
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Итак, после некоторого взлома мы пришли к следующему:

class authenticate:
   # start empty key
   key = None

   @classmethod
   """ add the token """
   def set_key(cls, token):
       cls.token = token

   def __init__(self, func=None):
       if func is not None:
           self.func = func
       else:
           print('no function')

   def __call__(self, *arg):
       """
       add authentication to function func
       """
       ret = self.func(*arg, auth_key=self.key)
       return ret

@authenticate
def f1(a, key):
    data = a
    result = requests.get(1, data, key)
    return result

Затем вы можете запустить код, например:

authentication_key = 'token'

print('Initiate class')
authenticate().set_key(key=authentication_key)

print('Run f1(5)')
a1 = f1(5) # no token needed!
a2 = f2(6, 12) # again no token needed as it is in the decorator
print(a1)

Это работает более или менее так, как я надеялся, и я нахожу его чище, чем методы класса. Если у кого-то есть лучшее предложение или улучшения, дайте мне знать.

Другие вопросы по теме