python 设计出一套接口签名和验证
需要app_id、secret 需要提前准备好作为密钥
生成签名函数
import hmac, hashlib, json def generate_signature(http_method, uri_path, args, body, secret): """ 生成签名的函数。 :param http_method: HTTP方法,例如"GET"或"POST" :param uri_path: 请求的URI路径 :param args: 请求的参数(字典形式) :param secret: 用于生成签名的密钥(字节类型) :return: 生成的签名(十六进制字符串形式) """ # 将HTTP方法转换为大写 http_method = http_method.upper() if not body: content_md5 = '' else: # 请求内容的MD5哈希值 content_md5 = hashlib.md5(json.dumps(body).encode('utf-8')).hexdigest() # 将请求参数按键名排序并生成参数字符串 keys = sorted(args.keys()) args_to_sign = [] for k in keys: v = args.get(k, '') if isinstance(v, (list, tuple)) and len(v) > 0: v = v[0] args_to_sign.append(f"{k}={v}") # 如果有参数,拼接成query string格式 if args_to_sign and len(args_to_sign) > 0: args_to_sign = '?' + '&'.join(args_to_sign) else: args_to_sign = '' # 生成待签名的字符串 string_to_sign = f"{http_method}\n{content_md5}\n{uri_path}{args_to_sign}" # 生成签名 signed = hmac.new(secret, string_to_sign.encode('utf-8'), digestmod=hashlib.sha256).hexdigest() # print("string_to_sign:", string_to_sign) return signed
验证函数
# -*- coding: utf8 -*- """ 梦美奇为内部其他服务提供接口如:趣作图 需要做签名认证 """ import hmac, hashlib, json from flask import request from web_app.models.developer import DeveloperApp def generate_signature(http_method, uri_path, args, body, secret): """ 生成签名的函数。 :param http_method: HTTP方法,例如"GET"或"POST" :param uri_path: 请求的URI路径 :param args: 请求的参数(字典形式) :param secret: 用于生成签名的密钥(字节类型) :return: 生成的签名(十六进制字符串形式) """ # 将HTTP方法转换为大写 http_method = http_method.upper() # 请求内容的MD5哈希值 if not body: content_md5 = "" else: content_md5 = hashlib.md5(body).hexdigest() # 将请求参数按键名排序并生成参数字符串 keys = sorted(args.keys()) args_to_sign = [] for k in keys: v = args.get(k, '') if isinstance(v, (list, tuple)) and len(v) > 0: v = v[0] args_to_sign.append(f"{k}={v}") # 如果有参数,拼接成query string格式 if args_to_sign and len(args_to_sign) > 0: args_to_sign = '?' + '&'.join(args_to_sign) else: args_to_sign = '' # 生成待签名的字符串 string_to_sign = f"{http_method}\n{content_md5}\n{uri_path}{args_to_sign}" # 生成签名 signed = hmac.new(secret, string_to_sign.encode('utf-8'), digestmod=hashlib.sha256).hexdigest() return signed, string_to_sign def very_signature(http_method, uri_path, args, body, wx_app_id, wx_sign): """ 验证签名 :param http_method: :param uri_path: :param args: :param secret: :param signature: :return: """ developer_app = DeveloperApp.get_by_app_id(wx_app_id) if not developer_app or not developer_app.secret: return False secret = developer_app.secret # 确保密钥是字节串 if isinstance(secret, str): secret = secret.encode('utf-8') sign, string_to_sign = generate_signature(http_method, uri_path, args, body, secret) if request.wx_request_debug: print("string_to_sign:", string_to_sign) print("wx_sign:", wx_sign, "sign:", sign) return wx_sign == sign if __name__ == '__main__': very_signature(request.method, request.path, args=request.values, body=request.get_data(), wx_app_id="wx_appid", wx_sign="wx_sign")