import hashlib import hmac import random import time from urllib.parse import quote # from flask_config import secretKey secretKey = '018f162e804f945ee6b23aebfa863639' class HSSignatureUrl: ''' HSSignatureUrl(url,route_param,query_param,body_param).url routerParms={ route_url:':name/:age', data:{ name:'001',age:'18' } } ''' def __init__(self, url, route_param, query_param, body_param): ''' 签名验证 :param url: url :param route_param: 路由参数 :param query_param: 问号参数 :param body_param: body参数 ''' url = url if url[-1:] == '/' else url + '/' self.url = '' self.param_dict = {} # 获取路由参数url self._get_header_url(url, route_param) # 获取签名后url self._get_signature_url(query_param, body_param) def _get_header_url(self, url, route_param): ''' 获取不带参数的url :param url: url :param route_param: 路由参数 :return: ''' if not route_param: self.url = url return param_data = route_param['data'] route_url = str(route_param['route_url']) # _route_url = '' for key in param_data.keys(): route_url = route_url.replace(':' + key, str(quote(param_data[key]))) self.param_dict[key] = param_data[key] self.url = url + route_url if self.url[-1:] == '/' else url + route_url + '/' def _get_signature_url(self, query_param=None, body_param=None): ''' 获取签名后的url :param query_param: :param body_param: :return: ''' _temp_param_url = '' if query_param: for key, value in query_param.items(): _temp_param_url += '&{}={}'.format(key, quote(str(value))) self.param_dict[key] = value time_stamp = self.get_time_stamp() nonce = self.get_random(5) signature_txt = self.make_signature(self.param_dict, body_param, time_stamp, nonce) signature = self.generateSinature(secretKey, signature_txt) self.url = '{}?timestamp={}&nonce={}&signature={}{}'.format(self.url, time_stamp, nonce, signature, _temp_param_url) @staticmethod def get_time_stamp() -> str: ''' 生成时间戳 :return: ''' return str(int(time.time())) @staticmethod def get_random(len) -> str: ''' 生成随机数 :param len: 随机数位数 :return: ''' return str(int(random.uniform(0, 1) * 10 ** int(len))) @staticmethod def make_signature(param_dict, body_param, time_stamp, nonce): ''' 待签名文本生成 :param param_dict: 参数字段 :param body_param: body参数 :param time_stamp: 时间戳 :param nonce: 随机数 :return: ''' _param_txt = '' _dict_key = sorted(param_dict.keys()) for key in _dict_key: _param_txt += '{}={}&'.format(key, param_dict[key]) if len(_param_txt) > 1: _param_txt = _param_txt[:-1] if body_param: _param_txt += str(body_param) _param_txt += str(time_stamp) + str(nonce) return _param_txt @staticmethod def generateSinature(secretKey, singnPlan) -> str: ''' 生成加密签名(哈希256算法) :param secretKey: 密钥 :param singnPlan: 密文 :return: 签名 ''' return hmac.new(bytes(secretKey, 'utf-8'), bytes(singnPlan, 'utf-8'), hashlib.sha256).hexdigest()