我写了一个基于函数的装饰器来处理我公司Web服务的身份验证:
def company_auth(path=None, method=None):
"""
Company Webservices authentication decorator
:param path: relative url of the endpoint;
:param method: http method used for the call
usage example:
@company_auth(path='/api/MO/GetDetails', method='GET')
def mo_get_details(**kwargs):
path = kwargs.pop('path')
headers = kwargs.pop('headers')
...
retrieve a valid token, compute the signature and pass to the inner function
the headers dict and the path parameter as kw arguments.
"""
def _signature_wrapper(fn, path, method):
def wrapper(*args, **kwargs):
token = get_valid_token()
signature_dict = {
'url': path,
'token': token.token,
'secret': token.secret,
'method': method
}
make_signature_results = make_signature(**signature_dict)
headers = {
'comp-header-date': make_signature_results['date'],
'comp-header-session-token': signature_dict['token'],
'comp-header-signature': make_signature_results['signature'],
'Content-Type': CONTENT_TYPE,
}
kwargs['headers'] = headers
kwargs['path'] = path
results = fn(*args, **kwargs)
return results
return wrapper
def decorating_fn(fn):
wrapper = _signature_wrapper(fn, path, method)
return update_wrapper(wrapper, fn)
return decorating_fn
def get_valid_token():
"""
get a valid token from db or generate a new one from company webservices.
"""
if not APIToken.objects.exists(): # this is a Django model
return set_new_token()
api_token = APIToken.objects.first()
if not api_token.is_valid:
return set_new_token()
else:
return api_token
虽然我通过Django ORM将生成的token / secret值保存在数据库中,但它工作正常。 我想避免这种情况,将其转变为基于类的装饰器,将其实例化为单例并将其导入不同的模块中。我想保留令牌/秘密对的值不在数据库上但在内存中(作为该实例的属性),如:
# Wanted CB Decorator
def CompanyAuth():
"""
Class Based Company Webservices authentication decorator
"""
def __init__(self, *args, **kwargs):
...
def __get__(self, *args, **kwargs):
...
def __call__(self, *args, **kwargs):
...
comp_auth = CompanyAuth()
# the singleton can then be imported by other modules and used
它是否可行以及如何实现这一目标?