支付系统是电商和源码交易平台的核心命脉,一旦出现安全漏洞,不仅导致资金损失,更可能引发用户信任崩塌。本文基于实战经验,系统梳理 Python 支付系统的安全实践方案,涵盖数据传输加密、签名验签、SQL 注入防护、CSRF/XSS 防御、敏感信息脱敏以及分布式风控机制,每个模块都附有可直接落地的代码示例。
无论你是在开发转卡码平台、源码商城,还是自己的支付中转服务,这些安全实践都能帮助你构建一个可靠、合规的支付系统。
一、数据传输加密:双向 TLS 与敏感字段加密
支付系统涉及用户隐私和交易数据,传输过程中必须加密。最基础的要求是开启 HTTPS(TLS 1.2+),但对于关键敏感字段(如银行卡号、身份证号),建议在应用层做二次加密。
使用 cryptography 实现 AES-256-GCM 加密
# pip install cryptography from cryptography.hazmat.primitives.ciphers.aead import AESGCM import os, base64 def encrypt_sensitive_data(plaintext: str, key: bytes) -> str: aesgcm = AESGCM(key) nonce = os.urandom(12) # GCM 模式推荐 12 字节 nonce ct = aesgcm.encrypt(nonce, plaintext.encode(), None) return base64.b64encode(nonce + ct).decode() def decrypt_sensitive_data(encrypted: str, key: bytes) -> str: raw = base64.b64decode(encrypted) nonce, ct = raw[:12], raw[12:] aesgcm = AESGCM(key) return aesgcm.decrypt(nonce, ct, None).decode() # 使用示例 KEY = os.urandom(32) # 生产环境从 KMS 或密钥管理服务获取 enc = encrypt_sensitive_data("622848****1234", KEY) print(f"加密后: {enc}") dec = decrypt_sensitive_data(enc, KEY) print(f"解密后: {dec}")
AES-256-GCM 模式同时提供加密和完整性校验,能有效防止篡改。生产环境中密钥不应硬编码在代码中,建议通过 HashiCorp Vault、AWS KMS 或阿里云 KMS 管理。
二、签名验签机制:防止请求伪造
支付系统中,无论是前端到后端,还是服务端到第三方支付网关,每个请求都需要签名验证。下面是一个标准的 HMAC-SHA256 签名实现:
import hashlib, hmac, json, time def generate_sign(payload: dict, secret: str) -> str: # 按字典序排序参数,保证签名一致性 sorted_keys = sorted(payload.keys()) sign_str = "&".join( f"{k}={payload[k]}" for k in sorted_keys ) sign_str += f"&key={secret}" return hashlib.md5(sign_str.encode()).hexdigest().upper() def verify_sign(payload: dict, sign: str, secret: str) -> bool: expected = generate_sign(payload, secret) return hmac.compare_digest(expected, sign) # 带时间戳防止重放攻击 def build_signed_request(data: dict, secret: str) -> dict: data['timestamp'] = int(time.time()) data['nonce_str'] = os.urandom(8).hex() data['sign'] = generate_sign(data, secret) return data
关键安全要点:
- 时间戳防重放:服务端校验时间戳与当前时间差不超过 5 分钟
- 随机 nonce:同一 nonce 不可重复使用(Redis 记录已用 nonce)
- 使用 hmac.compare_digest:防止时序攻击(timing attack)
- 参数排序:按 ASCII 字典序保证签名一致性
三、SQL 注入防护:ORM 与参数化查询
支付订单表是攻击者的首要目标。直接拼接 SQL 字符串是绝对禁止的。以下是正确的做法:
# ❌ 错误:字符串拼接(高危) cursor.execute(f"SELECT * FROM orders WHERE order_id='{order_id}'") # ✅ 正确:参数化查询 cursor.execute( "SELECT * FROM orders WHERE order_id = %s", (order_id,) ) # 🏆 最佳:使用 SQLAlchemy ORM from sqlalchemy.orm import Session from models import Order def get_order(db: Session, order_id: str) -> Order | None: return db.query(Order).filter( Order.order_id == order_id ).first()
使用 ORM 不仅能防注入,还天然支持事务管理——这对支付系统至关重要:
from sqlalchemy import create_engine from sqlalchemy.orm import sessionmaker engine = create_engine(DATABASE_URL, pool_size=10, max_overflow=20) SessionLocal = sessionmaker(bind=engine) def create_order(db: Session, user_id: int, amount: int) -> Order: try: order = Order( order_id=generate_order_id(), user_id=user_id, amount=amount, status='pending' ) db.add(order) db.commit() db.refresh(order) return order except Exception as e: db.rollback() raise
对于源码商城的转卡码系统,订单和卡密数据高度敏感,务必将数据库操作全部置于事务中,并设置合理的连接池参数防止连接耗尽。
四、CSRF 与 XSS 防护
CSRF 防护
付款操作、退款操作等必须防止跨站请求伪造。推荐使用 Double Submit Cookie 模式:
import secrets from flask import request, session, abort def generate_csrf_token() -> str: token = secrets.token_hex(32) session['csrf_token'] = token return token def verify_csrf_token() -> None: token = request.headers.get('X-CSRF-Token') \ or request.form.get('csrf_token') if not token or token != session.get('csrf_token'): abort(403, "CSRF token 验证失败")
XSS 防护
支付页面的任何用户输入输出都必须转义。使用 Jinja2 模板引擎时,默认开启自动转义,但注意 |safe 过滤器的使用:
# Flask + Jinja2 模板中 {{ user_input }} # ✅ 自动转义 HTML 特殊字符 {{ user_input|safe }} # ⚠️ 仅在确信内容安全时使用 # Python 中手动转义 import html safe_text = html.escape(user_input, quote=True)
五、敏感信息脱敏与日志安全
支付系统的日志可能包含大量敏感信息,如手机号、银行卡号、身份证号。必须对日志中的敏感字段做脱敏处理:
import re def mask_sensitive(text: str) -> str: # 脱敏手机号:138****5678 text = re.sub(r'(1[3-9]\d)\d{4}(\d{4})', r'\1****\2', text) # 脱敏银行卡号:622848******1234 text = re.sub(r'(\d{6})\d{6,10}(\d{4})', r'\1******\2', text) # 脱敏身份证号 text = re.sub(r'(\d{6})\d{8,10}(\d{4})', r'\1********\2', text) # 脱敏支付密码关键字 text = re.sub(r'(password|pwd|secret|sign_key)=[^&\s]+', r'\1=******', text, flags=re.I) return text # 使用 logging Filter 自动脱敏 import logging class SensitiveFilter(logging.Filter): def filter(self, record): if hasattr(record, 'msg') and isinstance(record.msg, str): record.msg = mask_sensitive(record.msg) return True logger = logging.getLogger('payment') logger.addFilter(SensitiveFilter()) logger.info("用户 13812345678 支付成功,卡号 6228481234567890") # 日志输出:用户 138****5678 支付成功,卡号 622848******7890
六、分布式风控机制
使用 Redis 实现分布式频率限制和风控检测,能有效拦截恶意调用:
import redis.asyncio as aioredis
from datetime import datetime
r = aioredis.Redis.from_url("redis://localhost:6379/0")
async def check_risk(user_id: str, ip: str) -> dict:
now = int(datetime.utcnow().timestamp())
window = 60 # 60 秒窗口
risk_score = 0
reasons = []
# 1. 检查 IP 请求频率(每分钟限制 30 次)
ip_key = f"ratelimit:ip:{ip}:{now // window}"
ip_count = await r.incr(ip_key)
await r.expire(ip_key, window + 5)
if ip_count > 30:
risk_score += 30
reasons.append("IP 请求频率过高")
# 2. 检查用户操作频率
user_key = f"ratelimit:user:{user_id}:{now // window}"
user_count = await r.incr(user_key)
await r.expire(user_key, window + 5)
if user_count > 10:
risk_score += 20
reasons.append("用户操作过于频繁")
# 3. 检查同一 IP 关联多个用户
ip_user_key = f"risk:ip_users:{ip}"
await r.sadd(ip_user_key, user_id)
await r.expire(ip_user_key, 3600)
user_count_for_ip = await r.scard(ip_user_key)
if user_count_for_ip > 5:
risk_score += 25
reasons.append("IP 关联用户数异常")
return {"risk_score": risk_score, "blocked": risk_score > 50, "reasons": reasons}
# 风控中间件
async def risk_middleware(request, call_next):
user_id = request.headers.get("X-User-Id", "anonymous")
ip = request.client.host
result = await check_risk(user_id, ip)
if result["blocked"]:
return JSONResponse(
status_code=429,
content={"error": "触发风控", "reasons": result["reasons"]}
)
return await call_next(request)
七、安全配置清单
最后,整理一份支付系统的安全配置自检清单,建议每次部署前逐项核对:
| 项目 | 检查内容 | 优先级 |
|---|---|---|
| HTTPS | TLS 1.2+,禁用 SSLv3/TLSv1.0 | P0 |
| 签名验签 | 所有接口强制签名校验 | P0 |
| 防重放 | 时间戳 + nonce 双重校验 | P0 |
| 参数化查询 | 禁止 SQL 字符串拼接 | P0 |
| CSRF 令牌 | 写操作接口验证 CSRF Token | P1 |
| 敏感数据加密 | 数据库存储加密(AES-256-GCM) | P1 |
| 日志脱敏 | 脱敏后才能写入日志文件 | P1 |
| 频率限制 | IP + 用户双层限流 | P1 |
| 事务管理 | 订单操作全部事务包裹 | P1 |
| 密钥轮换 | 签名密钥每 90 天轮换 | P2 |
| 错误信息 | 不向用户暴露内部栈信息 | P2 |
| 审计日志 | 所有管理操作留下审计轨迹 | P2 |
支付安全是一个持续迭代的过程,没有一劳永逸的方案。建议定期进行安全审计和渗透测试,关注 OWASP Top 10 的最新动态。
推荐工具:我们的 转卡码系统 V3 内置了上述所有安全机制——自动 AES-256 数据加密、HMAC-SHA256 签名验证、Redis 分布式限流以及完整的防注入 ORM 封装,开箱即用。配合 Codex Desktop 进行代码审查,能进一步提升支付系统的安全性。