本文目录导读:

我来为您介绍Python中生成接口签名的常见方法,这里以几种典型的签名算法为例:
HMAC-SHA256 签名(最常用)
import hashlib
import hmac
import time
import json
class APISignature:
def __init__(self, secret_key):
self.secret_key = secret_key
def generate_signature(self, params, timestamp=None):
"""
生成HMAC-SHA256签名
:param params: 请求参数字典
:param timestamp: 时间戳(可选)
:return: 签名字符串
"""
if timestamp is None:
timestamp = int(time.time())
# 1. 参数排序(按key排序)
sorted_params = sorted(params.items(), key=lambda x: x[0])
# 2. 拼接参数字符串
param_str = '&'.join([f"{k}={v}" for k, v in sorted_params])
# 3. 添加时间戳和密钥
sign_str = f"{param_str}×tamp={timestamp}&key={self.secret_key}"
# 4. 生成签名
signature = hmac.new(
self.secret_key.encode('utf-8'),
sign_str.encode('utf-8'),
hashlib.sha256
).hexdigest().upper()
return signature, timestamp
# 使用示例
def api_request_example():
# 初始化签名器
secret_key = "your_secret_key_here"
signer = APISignature(secret_key)
# 请求参数
params = {
"app_id": "test_app",
"method": "get_user_info",
"user_id": "12345",
"version": "1.0"
}
# 生成签名
signature, timestamp = signer.generate_signature(params)
print(f"签名: {signature}")
print(f"时间戳: {timestamp}")
# 构造完整请求参数
request_params = params.copy()
request_params['timestamp'] = timestamp
request_params['sign'] = signature
return request_params
MD5签名(传统方式)
import hashlib
import time
class MD5Signature:
def __init__(self, app_secret):
self.app_secret = app_secret
def generate_signature(self, params):
"""
生成MD5签名
"""
# 1. 移除sign参数(如果有)
params.pop('sign', None)
# 2. 按key排序
sorted_keys = sorted(params.keys())
# 3. 拼接字符串
sign_str = self.app_secret
for key in sorted_keys:
sign_str += f"{key}{params[key]}"
sign_str += self.app_secret
# 4. MD5加密
signature = hashlib.md5(sign_str.encode('utf-8')).hexdigest().upper()
return signature
# 使用示例
def md5_sign_example():
app_secret = "your_app_secret"
signer = MD5Signature(app_secret)
params = {
"name": "张三",
"age": 25,
"timestamp": int(time.time())
}
signature = signer.generate_signature(params)
params['sign'] = signature
print(f"参数: {params}")
print(f"签名: {signature}")
RSA签名(更安全)
from Crypto.Signature import PKCS1_v1_5
from Crypto.Hash import SHA256
from Crypto.PublicKey import RSA
import base64
class RSASignature:
def __init__(self, private_key_path):
with open(private_key_path, 'r') as f:
self.private_key = RSA.import_key(f.read())
def generate_signature(self, data):
"""
生成RSA签名
"""
# 1. 将数据转换为字符串
if isinstance(data, dict):
# 排序后转为JSON
sorted_data = dict(sorted(data.items()))
message = json.dumps(sorted_data, separators=(',', ':'))
else:
message = str(data)
# 2. 计算哈希
hash_obj = SHA256.new(message.encode('utf-8'))
# 3. 生成签名
signer = PKCS1_v1_5.new(self.private_key)
signature = signer.sign(hash_obj)
# 4. Base64编码
return base64.b64encode(signature).decode('utf-8')
# 使用示例
def rsa_sign_example():
signer = RSASignature("private_key.pem")
params = {
"order_id": "20231201001",
"amount": 100.50,
"currency": "CNY"
}
signature = signer.generate_signature(params)
print(f"RSA签名: {signature}")
完整的客户端-服务端签名验证示例
import hashlib
import hmac
import time
import json
from flask import Flask, request, jsonify
# ============== 客户端 ==============
class APIClient:
def __init__(self, app_key, app_secret, base_url):
self.app_key = app_key
self.app_secret = app_secret
self.base_url = base_url
def generate_signature(self, params):
"""生成签名"""
# 基础参数
params['app_key'] = self.app_key
params['timestamp'] = int(time.time())
params['nonce'] = str(time.time_ns()) # 随机字符串
# 排序并拼接
sorted_keys = sorted(params.keys())
sign_str = self.app_secret
for key in sorted_keys:
sign_str += f"{key}{params[key]}"
sign_str += self.app_secret
# 生成签名
params['sign'] = hashlib.md5(sign_str.encode('utf-8')).hexdigest().upper()
return params
def send_request(self, endpoint, data=None):
"""发送API请求"""
import requests
params = data or {}
signed_params = self.generate_signature(params)
response = requests.post(
f"{self.base_url}{endpoint}",
json=signed_params
)
return response.json()
# ============== 服务端 ==============
app = Flask(__name__)
# 存储应用密钥(实际使用时应该从数据库获取)
APP_SECRETS = {
"test_app": "test_secret_key"
}
@app.route('/api/verify', methods=['POST'])
def verify_api_request():
"""验证API请求签名"""
data = request.get_json()
# 获取必要参数
app_key = data.get('app_key')
timestamp = data.get('timestamp')
nonce = data.get('nonce')
client_sign = data.get('sign')
# 验证参数完整性
if not all([app_key, timestamp, nonce, client_sign]):
return jsonify({"error": "Missing required parameters"}), 400
# 获取服务端密钥
server_secret = APP_SECRETS.get(app_key)
if not server_secret:
return jsonify({"error": "Invalid app_key"}), 401
# 验证时间戳(防止重放攻击)
current_time = int(time.time())
if abs(current_time - int(timestamp)) > 300: # 5分钟有效期
return jsonify({"error": "Request expired"}), 401
# 验证签名
# 移除sign参数,重新生成签名
verify_data = data.copy()
verify_data.pop('sign')
# 按客户端相同的方式生成签名
sorted_keys = sorted(verify_data.keys())
sign_str = server_secret
for key in sorted_keys:
sign_str += f"{key}{verify_data[key]}"
sign_str += server_secret
server_sign = hashlib.md5(sign_str.encode('utf-8')).hexdigest().upper()
if server_sign != client_sign:
return jsonify({"error": "Invalid signature"}), 401
return jsonify({"message": "Signature verification passed", "data": data})
if __name__ == '__main__':
app.run(debug=True)
常用的签名规范总结
签名步骤
- 参数排序:按参数名的字典序排序
- 拼接字符串:将排序后的参数按
key=value格式拼接 - 添加密钥:在拼接字符串前后添加密钥
- 加密生成:使用MD5、SHA256等算法加密
- 返回结果:通常转成大写16进制字符串
最佳实践建议
class BestPracticeSignature:
"""签名最佳实践"""
@staticmethod
def generate(params, secret_key, version='v2'):
"""生成签名"""
# 1. 移除空值和sign参数
params = {k: v for k, v in params.items()
if v is not None and k != 'sign'}
# 2. 添加必需参数
params.setdefault('timestamp', int(time.time()))
params.setdefault('nonce', str(uuid.uuid4().hex[:16]))
params.setdefault('version', version)
# 3. 参数排序
sorted_params = sorted(params.items())
# 4. 拼接签名串
sign_parts = []
for key, value in sorted_params:
if isinstance(value, dict):
value = json.dumps(value, separators=(',', ':'))
sign_parts.append(f"{key}={value}")
sign_str = '&'.join(sign_parts)
sign_str = f"{secret_key}{sign_str}{secret_key}"
# 5. 生成签名
signature = hashlib.md5(sign_str.encode()).hexdigest().upper()
return signature, params
# 使用示例
def main():
# 准备参数
params = {
"method": "user.info",
"uid": 1001,
"name": "测试用户"
}
# 生成签名
signature, signed_params = BestPracticeSignature.generate(
params,
"your_secret_key"
)
signed_params['sign'] = signature
print(f"签名后的请求参数:\n{json.dumps(signed_params, indent=2)}")
这些签名方法的选择取决于您的具体需求:
- HMAC-SHA256:最常用,安全性高
- MD5:简单快速,适合对安全性要求不高的场景
- RSA:最安全,但需要管理密钥对
实际使用时,建议根据API文档选择合适的签名算法。