凌晨 2 点 47 分,一条告警短信把站长从床上拽了起来:"接口调用量异常,过去一小时查询接口请求 41 万次。"他盯着后台日志,发现这些请求来自几十个 IP、几百个商户号,每一个都卡在限流阈值之下,单独看毫无异常,加在一起却把他的商户号推上了通道方的风控名单。
第二天上午,通道方的风控电话准时打来,理由是"短时间内异常高频查询行为",限期整改,否则冻结结算。那一刻他才明白:接口被刷,最怕的不是刷崩服务器,而是刷脏资质。服务器扛住了、数据库没爆,可商户号在通道风控系统里的画像,已经被这一晚上打烂了,想申诉都拿不出一句能自证清白的话。
所以"支付接口被刷怎么办",答案从来不是某一个技术点,而是一套组合拳:限流、验签、风控、黑名单,四道防线各管一段。这篇文章把四道防线拆成能直接落地的规则,有几个点是踩坑总结出来的——被刷的重灾区其实是查询接口和回调接口而不是下单接口、限流必须分层光有全局限流等于没设防、验签防的是重放不是假请求。网上搜"支付接口被刷",基本没人讲透这些。
先搞清楚:刷的到底是什么,最容易漏防的是哪两个
很多人一听到"接口被刷",脑子里第一反应是"有人脚本批量下单"。这确实是刷,但它只是最粗浅的一种。真正值得警惕、也最容易被漏防的,是另外两个接口。
先说清楚,一个支付系统对外的接口,大概就三类:下单接口、查询接口、回调接口。这三类里,攻击者的兴趣完全不一样:
- 下单接口:刷它的人,目的是制造海量无效订单,压垮你的数据库,或者用垃圾订单把你的通道"喂饱",触发通道方的风控。这种刷法最显眼,也最容易被你发现。
- 查询接口:这才是重灾区。刷查询接口的人,往往不是冲着你来的,而是在"撞库"或者"探测"——他拿一堆订单号逐个查,看你的订单号有没有规律、能不能猜出来、别人的订单能不能被枚举出来。更阴的是,查询接口的调用成本低、不产生资金,所以很多系统的下单接口做了验签,查询接口却完全裸奔。攻击者专挑这个软柿子捏。
- 回调接口:这是最危险的一个。刷回调接口的人,图的是"伪造支付成功"。他构造一个假的回调请求,模拟通道告诉你"这笔订单支付成功了",如果你的回调接口不验签、不校验金额和订单号,系统就会误判,直接发货或者入账。这是实打实的资损,不是骚扰。
看到这你就明白了:被刷这件事,下单接口只是"明枪",查询接口和回调接口才是"暗箭"。你只防下单,等于把最值钱的两个口子敞开着。下面四道防线,下单、查询、回调三个接口要全覆盖,一个都不能漏。
第一道防线:限流——必须分层,光有全局限流等于没设防
限流是四道防线里最基础的一道,但也是被误解最深的一道。很多人以为"给接口加个限流,每秒最多 100 次"就完事了。这种单层限流,在真实攻击面前基本等于没有。
为什么?因为攻击者的请求是"分散"的。他可以用几十个 IP、几十个商户号、几十万个不同的订单号,把你的"每秒 100 次"这个阈值,拆成每个维度都低于阈值、但总量依然巨大的流量。你只设一个全局阈值,他轻轻松松就绕过去了。
所以限流必须是分层的、多维度的,至少要有这么几层,而且每一层都要有独立的阈值:
- 全局限流:整个系统每秒最多处理多少请求。这是兜底,防止系统被整体打崩。
- 按商户限流:单个商户号每秒、每分钟最多多少次。这是最核心的一层,因为攻击者通常是通过某个商户的密钥来刷的,把单个商户卡死,攻击面就小了。
- 按 IP 限流:单个来源 IP 的请求频率。这层要配合"真实 IP"来用,如果你套了 CDN 或者反代,一定要把真实 IP 从 X-Forwarded-For 里正确取出来,否则你限的是 CDN 的 IP,等于白限。
- 按订单号限流:同一个订单号,单位时间内只允许查询/回调多少次。这层是为了防"撞库式"的暴力查询。
四层叠起来,攻击者无论从哪个维度进攻,都会撞上其中一层。这才是真正有效的限流。
算法上,很多人纠结"令牌桶"还是"滑动窗口"。我的建议很直接:下单接口用令牌桶,查询和回调接口用滑动窗口。令牌桶允许一定的突发(比如促销时订单瞬间涌入),适合下单这种"有波峰"的场景;滑动窗口对"连续高频"的判定更严格,适合查询、回调这种"本不该有突发、一有突发就是异常"的场景。别在算法上来回纠结,先把分层做对,算法是其次的。
第二道防线:验签——它防的不是"假请求",是"重放"
验签是支付行业的老规矩了,但很多人对它的理解是错的。大部分人以为验签是为了"确认这个请求是通道/商户发来的,不是别人伪造的"。这个理解只对了一半。
验签真正要防的,是重放攻击。什么叫重放?就是攻击者截获了一个合法的、已经签好名的请求,然后把这个请求原封不动地再发一次、发一百次。因为签名是合法的,你的系统验签会通过,于是攻击者就"合法地"刷了你的接口。
光有签名,是防不住重放的。要防重放,必须把三样东西绑在一起:时间戳、随机数(nonce)、签名本身。
- 时间戳:请求里带一个时间戳,你服务端校验它和当前时间的差值,超过一个窗口(比如 5 分钟)就拒绝。这能防止攻击者拿一个"很久以前"的合法请求来重放。
- 随机数 nonce:每个请求带一个唯一的随机串,你服务端把这个 nonce 记下来,短期内(比如 5 分钟)同一个 nonce 只允许出现一次。这能防止攻击者在时间窗口内把同一个请求重放无数次。
- 签名:把参数 + 时间戳 + nonce 一起按约定算法(MD5 或 RSA)算出一个签名,服务端用同样的方式重算一遍,比对是否一致。
这三者缺一不可。缺了时间戳,攻击者可以无限重放旧请求;缺了 nonce,攻击者可以在窗口内疯狂重放;缺了签名,前面两个都白搭。很多人只做了签名,没做时间戳和 nonce,结果签名验得死死的,重放照样打得进来。
关于签名到底用 MD5 还是 RSA、各自的适用场景和坑,我在支付回调sign签名:MD5和RSA到底有什么区别、该用哪个里拆得很细,这里不展开。你只要记住一点:验签的完整闭环,是"时间戳 + nonce + 签名"三件套,不是光算一个 MD5 就完事。
第三道防线:风控——要"实时拦截",而不是"事后追查"
限流和验签,解决的是"请求是不是异常"的问题;但有些请求,限流没超阈值、验签也合法,它依然是有问题的。这时候就需要风控上场。
风控的核心思路,是在请求进来的一瞬间,根据它的特征判断"这个请求该不该放行"。这里我要强调一个很多人忽视的区别:风控必须是实时拦截,而不是"T+1 离线分析"。
什么叫离线分析?就是你每天晚上跑一遍数据分析,发现"昨天有个商户的请求量异常",然后第二天再去处理。这种事后追查,对"刷接口"这种攻击来说几乎没用——因为攻击者一个晚上就能把你的商户画像刷脏,等你第二天发现,损失已经造成了,通道方的风控预警也早就触发了。
所以风控规则必须挂在请求链路上,实时跑。一套能落地的实时风控,至少要有这几类规则:
- 频率异常:某商户、某 IP 的请求频率突然暴涨(比如是平时均值的几十倍),直接拦截。这是最基础的一条。
- 金额异常:某商户短时间内大量出现"极小金额"或"完全相同的金额"的订单,这往往是脚本批量下单的特征。
- 时间异常:某商户的订单集中在凌晨三四点这种"非正常营业时间"突然爆发,要重点盯。
- 行为异常:同一批订单号反复查询、同一 IP 反复尝试回调查询不同的订单号,这种"探测"行为要直接拉黑。
这些规则,说白了就是把"一个有经验的运维半夜盯着日志看出来的东西",固化成代码,让系统 24 小时自动盯。规则不用多,关键是每条规则都要能实时命中、实时拦截,而不是事后打个报告。
风控和降级、切换其实是同一套体系的延伸——通道出问题要降级,请求出问题要拦截,本质都是"系统自己发现问题、自己处理,不等人工"。关于通道侧的风控到底怎么运作、触发预警后该怎么自救,我在资金被冻结别慌:商户风控申诉的完整自救步骤里写过完整的申诉思路,值得配合着看。
第四道防线:黑名单——动态评分,而不是一刀切拉黑
前面三道防线拦下来的"坏请求",最终要落到一个处置动作上,这个动作通常是"拉黑"。但黑名单这个词,很多人又理解窄了——以为就是"把这个 IP 或商户号永久拉黑"。这种一刀切的思路,在真实业务里会误伤一大片。
为什么不能一刀切?因为"异常"和"攻击"之间,隔着一条很宽的灰色地带。一个正常商户,可能因为做活动、流量突然暴涨,触发了你的频率异常规则,你如果直接永久拉黑,等于把一个大客户赶走了。一个正常用户,可能因为网络重试,短时间内查了同一个订单好几次,你如果拉黑他的 IP,他下次想用你的服务都用不了。
所以黑名单的正确做法,是动态评分,而不是"黑白二分"。我的落地思路是这样的:
- 给每个商户号、每个 IP 维护一个风险分,初始为 0。
- 触发一次轻度异常(比如单次频率超阈值),风险分 +10;触发一次重度异常(比如查到了别人的订单、伪造回调),风险分 +50。
- 风险分达到一个阈值(比如 100),进入"临时拉黑",拉黑一段时间(比如 24 小时),到期自动解除。
- 风险分会随时间衰减——如果一段时间没有新的异常,风险分慢慢降回去。这样"偶发一次抖动"的商户,不会一直被钉在黑名单上。
- 只有风险分冲得特别高、且反复触发重度异常的,才做永久拉黑。
这套"加减分 + 时间衰减 + 分级处置"的机制,核心就一句话:让系统既能果断拦住坏人,又不至于误伤好人。支付行业最怕的就是"宁可错杀一千",因为你错杀的那个商户,可能转头就带着量去了别家。
四道防线,怎么串成一套组合拳
单独看,四道防线各有各的职责;但它们真正的威力,在于串起来、按顺序协同。一个请求进来,正确的处理顺序应该是这样的:
- 第一关,验签:时间戳、nonce、签名三件套先验证,验不过的直接拒绝,连后面的资源都不给它消耗。这是最前置、成本最低的拦截。
- 第二关,限流:验签过了,再看这个请求有没有超限——全局、商户、IP、订单号四层各查一遍,超了就拒绝或降级处理。
- 第三关,风控:限流没超,但请求的特征可疑(金额、时间、频率异常),交给实时风控规则判断,可疑的拦截。
- 第四关,黑名单:前面任一层判定为异常的来源,都给它的风险分加分,分数到了就拉黑。拉黑的名单,又反过来喂给验签和限流,让它们更早地拦截。
注意这个顺序不是随便排的:验签在最前,因为它最便宜、最前置,能在请求还没进到业务逻辑之前就把它挡掉。如果把限流放在验签前面,攻击者用海量假请求就能把你的限流计数器打满,反而把正常请求挤掉了。顺序错了,防线之间会互相拖累。
最后说一句我特别想强调的:接口被刷这件事,防的不是"服务器崩",是"资质脏"。你服务器扛住了、数据库没爆,但商户号在通道那边的风控画像被刷脏了,这才是真正伤筋动骨的损失,而且很难挽回。所以这套组合拳,与其说是"防攻击",不如说是"守住你在通道眼里的清白"。四道防线搭好了,你的接口才经得起别人半夜来折腾。