Python接口签名案例如何生成校验签名

wen python案例 25

本文目录导读:

Python接口签名案例如何生成校验签名

  1. HMAC-SHA256 签名(最常用)
  2. MD5签名(传统方式)
  3. RSA签名(更安全)
  4. 完整的客户端-服务端签名验证示例
  5. 常用的签名规范总结

我来为您介绍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}&timestamp={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)

常用的签名规范总结

签名步骤

  1. 参数排序:按参数名的字典序排序
  2. 拼接字符串:将排序后的参数按key=value格式拼接
  3. 添加密钥:在拼接字符串前后添加密钥
  4. 加密生成:使用MD5、SHA256等算法加密
  5. 返回结果:通常转成大写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文档选择合适的签名算法。

抱歉,评论功能暂时关闭!