fastapi: 第二十章:用中间件做接口验证签名
一,验证签名的作用:
在 FastAPI 中,使用中间件进行接口签名验证(Signature Verification)能有效防止接口被篡改和防重放攻击。
你可以通过继承
你可以通过继承
BaseHTTPMiddleware 来实现全局的请求拦截与签名校验。 签名生成规则(客户端与服务端约定)
通常签名的生成包含三个核心步骤:
- 收集参数:提取所有请求参数(Query 或 JSON Body)。
- 拼接字符串:将参数按字母顺序排序,拼接成
key=value&key=value的形式,并在末尾加上私钥secret_key。 - 哈希运算:使用 MD5 或 SHA-256 计算哈希值作为签名(如
sign)。
说明:
timestamp: 验证时间戳(防重放攻击)
sign: 客户端提交的签名字串
nonce: 一次性字符串,防止重复提交
二,代码:
中间件:
# app/middleware/api_sign.py
import hashlib
from fastapi import FastAPI, Request
import time
from starlette.middleware.base import BaseHTTPMiddleware
from starlette.responses import JSONResponse
from app.utils.tools import generate_md5
APP_KEY = "iphone"
APP_SECRET = "your_secret_key"
MAX_TIME_DIFF = 600
class SignatureMiddleware(BaseHTTPMiddleware):
async def dispatch(self, request: Request, call_next):
# 1. 过滤无需校验的路径
ignore_paths = ["/docs", "/openapi.json"]
if request.url.path in ignore_paths:
return await call_next(request)
# 2. 获取参数并校验合法性
sign = request.headers.get("X-Signature")
timestamp = request.headers.get("X-Timestamp")
nonce = request.headers.get("X-Nonce")
appkey = request.headers.get("X-Appkey")
print("sign:", sign)
print("timestamp:", timestamp)
# 检查是否过期
is_expired = abs(time.time() - int(timestamp)) > MAX_TIME_DIFF
print("is_expired:", is_expired)
if not sign or not timestamp or is_expired==False:
return JSONResponse(status_code=401, content={"detail": "Invalid signature or timestamp"})
# 3. 验证签名(此处简单示例:path + body + secret)
raw_str = f"{APP_KEY}{APP_SECRET}{timestamp}{nonce}"
print("raw_str:", raw_str)
md5_sign = generate_md5(raw_str)
print("md5_sign:", md5_sign)
if md5_sign != sign:
return JSONResponse(status_code=401, content={"detail": "Invalid signature"})
return await call_next(request)
调用中间件:
# main.py
from fastapi import FastAPI
from app.api import products, users, account
from app.core.exceptions import register_exception_handlers
from app.middleware.api_sign import SignatureMiddleware
# 创建FastAPI应用
app = FastAPI(title="我的API项目")
# 注册全局异常捕获
register_exception_handlers(app)
# 🚀 注册中间件
app.add_middleware(SignatureMiddleware)
# 注册路由模块
app.include_router(users.router)
app.include_router(products.router)
app.include_router(account.router)
三,测试 效果 :

浙公网安备 33010602011771号