本文目录导读:

我来为您提供几种Python签名校验的封装方案,从基础到进阶:
基础签名校验封装
HMAC-SHA256 签名方案
import hmac
import hashlib
import base64
import json
from typing import Dict, Any, Optional
from datetime import datetime
class HMACSignatureValidator:
"""HMAC-SHA256签名校验器"""
def __init__(self, secret_key: str):
"""
初始化签名校验器
:param secret_key: 密钥
"""
self.secret_key = secret_key.encode('utf-8')
def generate_signature(self, data: Dict[str, Any], timestamp: Optional[int] = None) -> str:
"""
生成签名
:param data: 待签名数据
:param timestamp: 时间戳(可选)
:return: 签名字符串
"""
# 添加时间戳
if timestamp is None:
timestamp = int(datetime.now().timestamp())
data['timestamp'] = timestamp
# 序列化并排序
message = json.dumps(data, sort_keys=True, ensure_ascii=False)
# 计算签名
signature = hmac.new(
self.secret_key,
message.encode('utf-8'),
hashlib.sha256
).hexdigest()
return signature
def verify_signature(self, data: Dict[str, Any], signature: str,
time_window: int = 300) -> bool:
"""
验证签名
:param data: 原始数据
:param signature: 待验证签名
:param time_window: 时间窗口(秒),默认5分钟
:return: 是否验证通过
"""
# 检查时间戳
if 'timestamp' not in data:
return False
timestamp = data['timestamp']
current_time = int(datetime.now().timestamp())
# 检查时间是否在窗口内
if abs(current_time - timestamp) > time_window:
return False
# 计算期望签名
expected_signature = self.generate_signature(data, timestamp)
# 使用hmac.compare_digest防止时序攻击
return hmac.compare_digest(expected_signature, signature)
RSA 签名校验封装
from cryptography.hazmat.primitives import hashes, serialization
from cryptography.hazmat.primitives.asymmetric import padding, rsa
from cryptography.hazmat.primitives import hashes
from cryptography.exceptions import InvalidSignature
import base64
class RSASignatureValidator:
"""RSA签名校验器"""
def __init__(self, public_key_path: str = None, private_key_path: str = None):
"""
初始化RSA签名校验器
:param public_key_path: 公钥文件路径
:param private_key_path: 私钥文件路径
"""
self.public_key = None
self.private_key = None
if public_key_path:
self.load_public_key(public_key_path)
if private_key_path:
self.load_private_key(private_key_path)
def load_public_key(self, path: str):
"""加载公钥"""
with open(path, 'rb') as f:
self.public_key = serialization.load_pem_public_key(f.read())
def load_private_key(self, path: str):
"""加载私钥"""
with open(path, 'rb') as f:
self.private_key = serialization.load_pem_private_key(
f.read(),
password=None
)
def generate_signature(self, message: str) -> str:
"""生成RSA签名"""
if not self.private_key:
raise ValueError("Private key not loaded")
signature = self.private_key.sign(
message.encode('utf-8'),
padding.PSS(
mgf=padding.MGF1(hashes.SHA256()),
salt_length=padding.PSS.MAX_LENGTH
),
hashes.SHA256()
)
return base64.b64encode(signature).decode('utf-8')
def verify_signature(self, message: str, signature: str) -> bool:
"""验证RSA签名"""
if not self.public_key:
raise ValueError("Public key not loaded")
try:
signature_bytes = base64.b64decode(signature)
self.public_key.verify(
signature_bytes,
message.encode('utf-8'),
padding.PSS(
mgf=padding.MGF1(hashes.SHA256()),
salt_length=padding.PSS.MAX_LENGTH
),
hashes.SHA256()
)
return True
except InvalidSignature:
return False
except Exception as e:
print(f"Verification error: {e}")
return False
API请求签名校验封装
import requests
from typing import Dict, Optional
from urllib.parse import urlencode
class APISignatureValidator:
"""API请求签名校验器"""
def __init__(self, app_id: str, secret_key: str):
"""
初始化API签名校验器
:param app_id: 应用ID
:param secret_key: 密钥
"""
self.app_id = app_id
self.secret_key = secret_key
self.validator = HMACSignatureValidator(secret_key)
def generate_request_signature(self, http_method: str, url: str,
params: Dict[str, Any] = None,
body: Dict[str, Any] = None) -> Dict[str, str]:
"""
生成API请求签名
:param http_method: HTTP方法
:param url: 请求URL
:param params: 查询参数
:param body: 请求体
:return: 包含签名的请求头
"""
timestamp = int(datetime.now().timestamp())
nonce = self._generate_nonce()
# 构建待签名字符串
signature_data = {
'app_id': self.app_id,
'method': http_method.upper(),
'url': url,
'timestamp': timestamp,
'nonce': nonce
}
if params:
signature_data['params'] = sorted(params.items())
if body:
signature_data['body'] = json.dumps(body, sort_keys=True)
# 生成签名
signature = self.validator.generate_signature(signature_data, timestamp)
return {
'X-App-ID': self.app_id,
'X-Timestamp': str(timestamp),
'X-Nonce': nonce,
'X-Signature': signature
}
def verify_request_signature(self, headers: Dict[str, str],
http_method: str, url: str,
params: Dict[str, Any] = None,
body: Dict[str, Any] = None) -> bool:
"""
验证API请求签名
:param headers: 请求头
:param http_method: HTTP方法
:param url: 请求URL
:param params: 查询参数
:param body: 请求体
:return: 是否验证通过
"""
try:
app_id = headers.get('X-App-ID')
timestamp = int(headers.get('X-Timestamp', '0'))
nonce = headers.get('X-Nonce')
signature = headers.get('X-Signature')
if not all([app_id, timestamp, nonce, signature]):
return False
# 构建验证数据
verify_data = {
'app_id': app_id,
'method': http_method.upper(),
'url': url,
'timestamp': timestamp,
'nonce': nonce
}
if params:
verify_data['params'] = sorted(params.items())
if body:
verify_data['body'] = json.dumps(body, sort_keys=True)
# 验证签名
return self.validator.verify_signature(verify_data, signature)
except Exception as e:
print(f"Verification error: {e}")
return False
def _generate_nonce(self) -> str:
"""生成随机数"""
import uuid
return str(uuid.uuid4())
使用示例
# 1. HMAC签名示例
hmac_validator = HMACSignatureValidator("my_secret_key_123")
# 生成签名
data = {"user_id": 123, "action": "login"}
signature = hmac_validator.generate_signature(data)
print(f"Generated signature: {signature}")
# 验证签名
result = hmac_validator.verify_signature(data, signature)
print(f"Verification result: {result}")
# 2. API请求签名示例
api_validator = APISignatureValidator("app_123", "secret_456")
# 生成请求签名
headers = api_validator.generate_request_signature(
"POST",
"https://api.example.com/user/login",
body={"username": "test", "password": "pass"}
)
print(f"Request headers: {headers}")
# 验证请求签名
is_valid = api_validator.verify_request_signature(
headers,
"POST",
"https://api.example.com/user/login",
body={"username": "test", "password": "pass"}
)
print(f"Verification result: {is_valid}")
装饰器实现
from functools import wraps
from flask import request, jsonify
def require_signature(validator):
"""API签名验证装饰器"""
def decorator(f):
@wraps(f)
def decorated_function(*args, **kwargs):
# 从请求中获取签名相关信息
headers = {
'X-App-ID': request.headers.get('X-App-ID'),
'X-Timestamp': request.headers.get('X-Timestamp'),
'X-Nonce': request.headers.get('X-Nonce'),
'X-Signature': request.headers.get('X-Signature')
}
# 验证签名
if not validator.verify_request_signature(
headers,
request.method,
request.url,
request.args,
request.json
):
return jsonify({"error": "Invalid signature"}), 401
return f(*args, **kwargs)
return decorated_function
return decorator
# 使用示例
app = Flask(__name__)
validator = APISignatureValidator("app_123", "secret_456")
@app.route('/api/secure', methods=['POST'])
@require_signature(validator)
def secure_endpoint():
return jsonify({"message": "Access granted"})
这些封装提供了不同安全级别的签名校验方案,您可以根据具体需求选择合适的方案,建议在生产环境中使用RSA签名,并确保密钥的安全存储。