4、API安全防护:API网关设计、请求频率限制、参数校验与过滤、API版本管理与废弃策略
聊到并发交易系统的API安全,我脑子里第一个蹦出来的词就是「门神」。你想想看,系统对外暴露的API接口,就像你家大门。门不够结实,或者看门的打瞌睡,那什么妖魔鬼怪都能进来。我在项目中见过太多因为API防护没做好,被爬虫爬死、被恶意刷单、甚至被SQL注入搞垮数据库的案例。嗯,今天我们就来把这扇门修得固若金汤。
4.1 API网关设计:系统的第一道防线
API网关是什么?说白了,它就是所有外部请求进入系统前的统一入口。我个人习惯把网关看作一个「智能保安」——它不负责具体业务,但负责检查每一个来访者的身份、意图、携带的行李。
核心职责:
- 身份认证:验证调用方是否合法(JWT、OAuth2、API Key)
- 流量控制:限制每秒/每分钟的请求量
- 协议转换:将外部HTTP请求转为内部RPC或消息
- 请求路由:根据路径将请求转发到正确的后端服务
- 日志审计:记录每一次调用的完整链路
我曾经在一个金融项目中,网关层只做了简单的路由转发,结果被攻击者利用API Key泄露的漏洞,连续三天半夜发起高频交易请求。那之后,我强制要求网关必须做三件事:IP白名单、请求签名校验、以及调用频率的实时监控。
下面这张图,是我在项目中常用的API网关核心流程。你可以看到,所有请求在到达业务服务之前,要经过层层过滤。
我的经验之谈:网关不要做太重。有些团队喜欢在网关里塞业务逻辑,比如数据转换、缓存预热。我个人建议网关只做「安检」和「分流」,业务逻辑交给后面的微服务。否则网关一旦挂了,整个系统就瘫痪了。
4.2 请求频率限制:别让一个用户拖垮整个系统
Rate Limiting,说白了就是「限流」。为什么要限流?因为总有人不守规矩。可能是竞争对手的爬虫,可能是用户手滑点了100次提交,也可能是DDoS攻击。我在一个电商秒杀项目中,就因为没做限流,被一个黄牛脚本在1秒内刷了5000次下单请求,数据库连接池直接打满,系统挂了整整20分钟。
常见的限流算法有四种,我整理了一个表格,方便你对比:
| 算法 | 原理 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|---|
| 固定窗口 | 按时间窗口计数,超限则拒绝 | 实现简单,内存占用小 | 窗口边界流量突刺 | 非关键路径的简单限流 |
| 滑动窗口 | 将时间窗口细分为小格,滑动统计 | 平滑流量,避免突刺 | 实现稍复杂 | 交易系统、支付接口 |
| 令牌桶 | 匀速放入令牌,请求消耗令牌 | 允许突发流量,控制平均速率 | 需要维护令牌桶状态 | API网关、微服务间调用 |
| 漏桶 | 请求进入桶中,以固定速率流出 | 强制平滑流量,绝对稳定 | 无法应对突发流量 | 数据库写入、消息队列 |
我个人最常用的是「令牌桶」算法。为什么呢?因为它允许短时间的突发流量——比如用户突然刷新页面,前几秒可以快速响应,但长期来看平均速率是可控的。这在交易系统中特别重要,因为用户的操作往往有「突发性」。
限流策略配置示例(基于令牌桶):
# 用户级别限流:每秒10个令牌,桶容量20
user:
rate: 10
capacity: 20
# IP级别限流:每秒100个令牌,桶容量200
ip:
rate: 100
capacity: 200
# 全局限流:每秒1000个令牌,桶容量2000
global:
rate: 1000
capacity: 2000
注意:限流一定要分层。我曾经见过一个项目只在网关层做了全局限流,结果一个恶意用户用100个IP同时攻击,每个IP的请求量都不大,但总和把系统打垮了。正确的做法是:用户级 + IP级 + 全局级,三层限流同时生效。
4.3 参数校验与过滤:别让脏数据进门
参数校验,听起来很简单对吧?不就是检查一下字段是不是空、格式对不对?但我在项目中踩过的坑告诉我,事情远没那么简单。
有一次,一个用户在前端输入了 '; DROP TABLE orders; -- 作为订单备注。前端没做校验,后端也没过滤,直接拼到了SQL查询里。嗯,你猜到了——那天的订单表差点被清空。从那以后,我定了一条铁律:永远不要信任任何来自客户端的数据。
参数校验应该做哪些事?我列了一个清单:
- 类型校验:数字字段必须是数字,不能是字符串或特殊字符
- 长度校验:防止超长字符串导致缓冲区溢出
- 格式校验:邮箱、手机号、身份证号必须符合正则
- 范围校验:金额不能为负数,年龄不能超过150
- SQL注入过滤:过滤
--、'、OR 1=1等危险字符 - XSS过滤:过滤
<script>、onerror等HTML标签
我的习惯:在网关层做第一道参数校验(格式、长度、类型),在业务层做第二道校验(业务逻辑、权限)。网关层只负责「粗筛」,业务层负责「精筛」。这样既保证了性能,又保证了安全。
4.4 API版本管理与废弃策略:优雅地老去
API版本管理,说白了就是「怎么让新旧接口和平共处」。我见过最粗暴的做法:直接改接口,然后通知客户端升级。结果呢?老版本客户端全部报错,用户骂声一片。
我个人推荐三种版本管理方式:
| 方式 | 示例 | 优点 | 缺点 |
|---|---|---|---|
| URL路径 | /v1/orders, /v2/orders | 直观、易于路由 | URL会变长 |
| 请求头 | Accept: application/vnd.myapp.v1+json | URL不变,更优雅 | 调试不方便 |
| 查询参数 | /orders?version=1 | 实现简单 | 容易被忽略 |
我个人习惯用URL路径方式。为什么?因为直观。运维同学看日志的时候,一眼就能看出请求的是哪个版本的接口。而且网关做路由转发也方便——直接根据路径前缀分发到不同的服务实例。
关于废弃策略,我曾经吃过一次大亏。一个老版本的API已经废弃了半年,但还有几个大客户在用。我直接强制下线了,结果客户的系统全部崩溃,商务团队差点被投诉到破产。从那以后,我制定了一套严格的废弃流程:
- 标记废弃:在响应头中加入
Deprecated: true,并在文档中标注 - 灰度通知:提前3个月通知所有已知客户端
- 逐步降级:先降低老版本的限流阈值,让新版本更有吸引力
- 强制下线:废弃满6个月后,返回410 Gone状态码
避坑指南:我曾经遇到过一个团队,废弃API时只改了文档,没改代码。结果老版本接口一直在运行,新版本却没人用。废弃API一定要在代码层面做限制——比如在网关层配置路由白名单,不在白名单里的版本直接返回404。
好了,API安全防护这块,核心就是这四个方面。网关是门神,限流是门槛,参数校验是安检,版本管理是后门。把这四样做好了,你的系统至少能挡住90%的常见攻击。剩下的10%,我们后面章节再聊。
公众号:蓝海资料掘金营,微信deep3321