Проверка подлинности клиента Python с помощью декораторов - PullRequest
0 голосов
/ 22 мая 2019

Я хочу построить клиент 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

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

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

1 Ответ

0 голосов
/ 23 мая 2019

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

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)

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

...