fastapi: 第二十章:用中间件做接口验证签名

一,验证签名的作用:

在 FastAPI 中,使用中间件进行接口签名验证(Signature Verification)能有效防止接口被篡改和防重放攻击
你可以通过继承 BaseHTTPMiddleware 来实现全局的请求拦截与签名校验。 
 
签名生成规则(客户端与服务端约定)
通常签名的生成包含三个核心步骤:
  1. 收集参数:提取所有请求参数(Query 或 JSON Body)。
  2. 拼接字符串:将参数按字母顺序排序,拼接成 key=value&key=value 的形式,并在末尾加上私钥 secret_key
  3. 哈希运算:使用 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)

三,测试 效果 :

image

posted @ 2026-06-12 10:52  刘宏缔的架构森林  阅读(15)  评论(0)    收藏  举报