验证码验证失败后的重试控制,核心不是”失败几次就锁号”,而是把失败计数、递增延迟、人机区分、熔断告警四层机制叠在一起,让正常用户几乎无感,让自动化脚本的成本高到不划算。
很多系统在验证码这块栽跟头,问题往往不在验证码本身多难识别,而在失败之后那套”再来一次”的逻辑太宽松,攻击者根本不需要破解图形,只要拿到一个可以无限重试的接口,就能把六位数字短信码慢慢试出来,下面按落地顺序拆开讲。
重试为什么会变成爆破入口
攻击者盯上的不是验证码,是失败后的放行规则
一个典型的登录接口,用户输错验证码后,服务端返回”验证码错误,请重试”,如果这个”重试”没有次数上限、没有时间窗口、没有维度绑定,攻击者用脚本每秒提交几十次,六位数字的空间在数学上并不大,真正的防线在于:同一个手机号、同一个IP、同一台设备,在单位时间内只能失败有限次。
三种最常见的失守场景
- 只按账号计数,不按IP和设备计数:攻击者用大量手机号轮换,每个号只试两三次,账号维度看着很正常,实际已经跑了几十万次。
- 验证码用过不失效:用户输错一次,原验证码还能继续用,等于给了攻击者同一张票反复入场的机会。
- 失败计数存在内存里:服务重启、多节点部署时计数各算各的,攻击者打在不同实例上,阈值形同虚设。
验证码失败重试次数怎么设置合理
这是后台配置里最常被问到的问题,答案不是一个固定数字,而是按场景分档,并且同时约束多个维度。
按业务场景分档设阈值
| 场景 | 单账号失败阈值 | 单IP失败阈值 | 单设备失败阈值 | 触发后动作 |
|---|---|---|---|---|
| 短信验证码登录 | 3 至 5 次 | 10 至 20 次/小时 | 5 至 8 次 | 冷却 10 分钟,转滑块 |
| 图形验证码提交 | 5 至 8 次 | 30 次/小时 | 10 次 | 降级为更严验证 |
| 支付密码+验证码 | 3 次 | 5 次/小时 | 3 次 | 直接锁定,人工核验 |
| 注册场景 | 5 次 | 20 次/小时 | 8 次 | 冷却并标记风险 |
阈值不要拍脑袋,上线前先用历史日志跑一遍,看正常用户的失败分布落在哪里,把阈值卡在正常用户第 99 百分位之外,这样误伤才可控。
计数维度要组合,不要单打一
业内专家指出,单一维度的限流几乎都会被绕过,建议至少组合四个维度:
- 账号维度:手机号或用户名,防单点爆破。
- IP 维度:防同一出口的高频尝试,注意 NAT 环境下要放宽。
- 设备指纹维度:基于浏览器指纹或 SDK 标识,防换号不换设备。
- 验证码凭证维度:一个验证码 ID 只允许校验固定次数,用完即废。
滑动窗口比固定窗口更贴近真实攻击
固定窗口的问题在于边界效应:攻击者在窗口切换点前后各打一波,实际频率翻倍,用 Redis 的 ZSET 做滑动窗口,记录每次失败的时间戳,查询时剔除窗口外的记录再计数,逻辑简单且准确。
# 记录一次失败,窗口 10 分钟 ZADD captcha:fail:uid:138xxxx 1690000000 "req-id-001" ZREMRANGEBYSCORE captcha:fail:uid:138xxxx 0 1689999400 ZCARD captcha:fail:uid:138xxxx EXPIRE captcha:fail:uid:138xxxx 600
短信验证码被恶意刷怎么办:重试层要打组合拳
短信被刷是成本最直接的攻击,一条短信几分钱,量大了一样疼,重试控制在这里要配合三件事。
逐级加严,而不是一步锁死
正常用户输错一次就锁号,体验很差,更合理的是阶梯式处置:
- 第 1 至 2 次失败:正常提示,刷新验证码。
- 第 3 次失败:强制出现滑块或行为验证。
- 第 4 至 5 次失败:进入冷却期,倒计时 5 至 15 分钟。
- 超过阈值:锁定并触发风控告警,必要时要求人工核验。
指数退避让脚本的性价比崩掉
每次失败后,下一次允许请求的间隔按 2 的幂增长,并加入随机抖动,攻击者要维持高频尝试,就必须同时维持大量并发会话,成本和暴露面都会上升,伪代码大致是:
delay = min(base (2 fail_count), max_delay) delay += random.uniform(0, jitter)
验证码必须一次性消费
无论校验成功还是失败,验证码 ID 都应立即作废或计数递减,校验失败后重新生成,用户拿到的是新票,这一条看似基础,却是很多系统的漏洞所在。
登录验证码防爆破方案怎么选:工程实现的四个要点
失败计数的原子性与过期
计数更新要用原子操作,避免并发下读改写丢失,Redis 的 INCR 配合 EXPIRE 是够用的,多节点部署时,计数必须落在共享存储上,本地缓存只做短时聚合。
与 WAF、风控的联动
重试计数是”点”上的数据,风控是”面”上的判断,把失败次数作为风险评分的一个因子推给风控,当设备指纹、IP 信誉、行为轨迹同时异常时,直接升级验证强度,而不是等次数攒满。
监控指标要提前埋
- 各维度失败率的分钟级曲线。
- 触发冷却和锁定的次数。
- 验证码下发量与校验量的比值,比值异常往往意味着刷量。
- 同一 IP 段、同一设备型号的集中失败。
行业共识认为,验证码类攻击的早期特征非常明显,多数情况下只要监控到位,能在造成实质损失前拦下来。
图形验证码防爆破配置教程里的关键参数
不管用自建还是第三方,配置时盯住这几个参数:
- 有效期:图形验证码通常 2 至 5 分钟,短信验证码 5 至 10 分钟,过期即废。
- 单码最大校验次数:建议 1 至 3 次,超过即失效。
- 失败冷却时长:按场景 5 至 15 分钟,可配置。
- 滑块难度分级:失败越多,轨迹判定越严。
- 是否绑定会话:验证码必须与会话或设备标识绑定,防止码贩子跨会话搬运。
成本与部署的现实考量
验证码防爆破私有化部署大概要多少钱,这个问题没有统一报价,自建方案的成本主要在人力:风控规则维护、日志存储、误伤调优,持续投入不小,第三方 SaaS 按调用量计费,中小体量下更省心;大型企业出于数据合规考虑,较大比例会选择私有化或混合部署,选型时别只看单价,把误伤率、人工核验成本和运维工时一起算进去才准。
Q&A:验证码重试控制常见问题
验证码失败重试次数设置少了会不会误伤正常用户?
会,阈值过严时,输入慢、网络差的用户容易被锁,解决办法不是放宽阈值,而是做区分:同一设备短时间内连续失败才加严,跨设备或跨天失败不累计;冷却期用倒计时提示代替直接报错;提供短信重发和人工申诉通道,上线前用历史数据回放,把误伤率压到可接受区间。
攻击者换 IP、换设备指纹,单维度限流还有用吗?
单维度确实不够,实际部署中,IP 和设备指纹的作用是提高攻击成本,不是绝对拦截,真正兜底的是账号维度的失败计数,加上验证码一次性消费和递增延迟,三者叠加后,攻击者每试一次都要付出新的 IP 或新的验证码成本,规模化爆破在经济上就不成立了。
验证码重试控制做到什么程度算达标?
一个可验证的标准是:同一账号连续失败超过设定阈值后,必须进入冷却或升级验证;同一验证码 ID 的校验次数有硬上限;失败计数在服务重启和多节点下保持一致;监控能在一分钟内发现异常失败率并告警,满足这四条,多数自动化爆破脚本会在成本和成功率之间主动放弃。
首发原创文章,作者:王坚,如若转载,请注明出处:https://idctop.com/article/784659.html

