Skip to content

短信验证码如何防止被恶意轰炸?如果有人不断请求发送验证码,你会如何限制? ​

  • 标签:后端、系统设计、场景题、安全

🏛 业务架构师 ​

短信验证码防轰炸,我按**"入口拦截 → 频率限制 → 通道管控 → 预算熔断"**四道防线答,并先点明业务代价:短信是按条计费的真实成本 + 对被轰用户的骚扰伤害——防轰炸既是省钱(资损)也是保口碑(合规投诉)。

第一道:入口人机校验(把脚本挡在门外)

  • 发送前强制滑块/行为验证码:脚本连第一道门都进不了,成本最低效果最好
  • 设备指纹:同一设备换号轮发 = 轰炸特征,直接拒绝

第二道:多维度频率限制(超越简单限流)

同手机号:   1分钟1条 / 1小时3条 / 24小时5条
同IP:       按NAT场景放宽阈值, 组合维度判断
同设备/账号: 单设备日上限(防换号)
号段风控:   虚拟运营商号段、接码平台常用号段库直接拒发或二次验证

关键细节:频控命中要静默处理——返回"发送成功"但不真发(防攻击者探测阈值边界),同时记录风控日志。

第三道:产品流程设计(让轰炸无利可图)

  • 验证码 + 行为绑定:注册流程要求"先验证邮箱/完成滑块/绑定邀请"才发短信——轰炸者只想烧你短信费,多一道门槛成本翻倍
  • 上行回复验证:关键场景要求用户回复短信内容才生效,接码平台收不到回复
  • 被轰用户保护:识别同一号码被高频请求(他人恶搞轰炸)→ 静默停发 + 通知用户"如非本人操作可忽略"——用户被骚扰的投诉是监管风险

第四道:预算熔断(最后的钱袋子)

  • 通道日发送总量预算(日常量 × 3~5 倍),达到 80% 告警、100% 自动停发
  • 单业务线独立预算:注册通道被刷爆不影响登录通道(爆炸域隔离)
  • 熔断必须自动化——凌晨三点被刷,等值班响应的一小时就是几千条的钱

收尾:防护上线后要复盘攻击成本:攻击者绕过一道防线的成本上升多少。短信防轰炸是持续对抗(接码平台也在升级),预算熔断保证的是"最坏情况的损失上限",这道底线永远不能撤。

🏗 系统架构师 ​

短信防轰炸我按发送前拦截(多层频控)→ 通道与成本控制 → 被攻击后的应急组织,核心思想:单点限流必被绕过,多维频控 + 行为验证 + 熔断兜底。

1. 发送前的多层频控(维度组合是关键) 单维度都能被绕(IP 有代理池、手机号是攻击目标本身就是变量),组合拳:

  • 手机号维度(保护单个用户):1 条/分钟、5 条/小时、10 条/天,阶梯限制
  • IP 维度:单 IP 每小时 N 条(阈值放宽些,防企业出口 NAT 误伤)
  • 设备指纹维度(最重要):Web 的 canvas/WebGL 指纹、App 的设备 ID,一台设备无论换多少 IP 只能发有限条——黑产换 IP 容易、换设备贵
  • 账号/会话维度:未登录场景用临时会话 ID 限制
  • 业务流程维度:必须先完成注册前几步(图形验证通过)才能触发短信;同一手机号重复发码需倒计时(60s)
  • 全部频控放 Redis 计数器(INCR + EXPIRE),Lua 保证原子

2. 行为验证前置(挡住机器) 发码前必须过滑动/点选验证码(人机识别),这是成本最低、效果最好的一层——脚本被挡在频控之前。再叠加:新设备/异地/高风险时段升级二次校验。

3. 手机号本身的治理

  • 号段黑名单:接码平台常用号段库、虚拟运营商风险号段
  • 空号/停机检测(第三方服务):不浪费发送成本
  • 风控名单:近期被投诉、被大量请求的号码降级处理

4. 通道与成本兜底(资损防线)

  • 全局日配额熔断:单业务通道每日上限(如 50 万条),触达即熔断 + 电话告警——半夜被刷也不会烧穿预算
  • 按业务拆通道签名(登录、营销分开),一个被攻击不殃及其他
  • 短信服务商配额与异常告警联动(发送量突增 5 倍自动暂停)

5. 事后与对抗:发送日志全量留存(溯源与执法);频控命中的特征回流风控(设备/IP 聚类识别团伙);定期复盘黑产绕过手段升级规则。

一句话:验证码拦机器、设备指纹锁终端、阶梯频控保用户、全局熔断保钱包。

💻 全栈开发专家 ​

短信轰炸的本质是短信资费被当攻击成本,我的防护是"发之前多道闸 + 总量熔断 + 事后识别"。

发送前置闸门(层层过滤)

  1. 图形/滑块验证码前置:人机校验在前,脚本批量请求第一道就被拦。
  2. 同手机号频控(Redis 计数器,最核心):
java
String k1 = "sms:min:" + phone;   // 1 分钟 1 条
String k2 = "sms:day:" + phone;   // 自然日 5 条
if (Boolean.FALSE.equals(redis.opsForValue().setIfAbsent(k1, "1", 60, SECONDS)))
    return reject("操作过于频繁");
if (redis.opsForValue().increment(k2) > 5) return reject("今日已达上限");
redis.expire(k2, Duration.untilTomorrow()); // 首次设置次日过期
  1. 多维频控:不只手机号维度——同 IP(每天 10 条)、同 deviceID、同用户账号(换手机号轰炸也没用),任一超限即拒。
  2. 号码风控:虚拟运营商号段、近期被投诉标记的号码、空号检测(前置检测接口),降低无效消耗。

总量熔断(保护资费的最后底线)

  • 全局预算:业务线当日短信总量上限(如 50 万条),达到 80% 告警、100% 熔断非核心模板,注册/登录验证码保底。
  • 分钟级速率:运营商通道本身有发送速率限制,自己在网关侧做匀速,防突刺触发通道降级。

事后识别与处置

  • 发送量突增告警(环比 5 分钟翻倍即触发),自动收紧阈值(日上限 5 → 2 条)。
  • 离线识别轰炸模式(同 IP 发不同号、同设备发不同号),号码和设备进黑名单。
  • 对被轰炸用户提供"免打扰"开关 + 专属客服通道。

易漏的坑

  • 验证码校验接口也要防爆破:6 位码错误 5 次作废,验证成功即删,别给人枚举机会。
  • 语音验证码、国际短信单独计价单独限流。
  • 前端倒计时只是体验,服务端频控才是真防线。