验证码与接口防刷完整落地方案

验证码与接口防刷完整落地方案

适用场景:登录、注册、找回密码、短信/邮件验证码发送、支付、提交表单等高危接口;目标:抵御爬虫、脚本批量刷接口、薅短信、暴力破解,同时兼顾正常用户体验 。

版本:V1.0 | 文档类型:技术方案 | 可直接交付开发评审

目录

  1. 风险概述
  2. 整体架构思路
  3. 验证码体系(多种验证码选型+落地规则)
  4. 接口防刷策略(限流、黑名单、风控、账号防护)
  5. 分层防护策略(网关层、应用层、业务层)
  6. 数据埋点与告警
  7. 降级与用户体验策略
  8. 部署与上线步骤
  9. 测试用例
  10. 运维与迭代

1. 风险概述

业务风险

  1. 短信验证码被批量刷取,产生高额短信资费,手机号被恶意注册。
  2. 登录接口暴力破解,账号被盗、撞库攻击。
  3. 接口被高频请求,服务器压力激增,服务不可用。
  4. 恶意批量提交表单,刷活动、刷优惠券、刷投票。

攻击来源

  • 自动化脚本、爬虫、代理IP池、打码平台、批量账号、肉鸡。

核心原则:多层防御,不要依赖单一验证码;验证码只是最后一道人机校验,限流+风控前置拦截。

2. 整体架构思路

分层防御模型(由外到内)

  1. CDN/网关层:IP基础限流、WAF拦截恶意特征、拦截高频异常IP
  2. 应用接口层:接口维度限流、设备指纹、Cookie/Token校验
  3. 业务层:验证码校验、账号维度风控、黑名单、行为检测
  4. 数据层:日志埋点、风控引擎、异常告警

核心思想:正常用户尽量不弹验证码;异常行为触发验证码;严重异常直接拒绝访问。

3. 验证码体系(落地规则)

3.1 验证码选型与使用场景

类型 适用场景 优点 缺点
图形验证码(滑块/点选) 前置拦截,高频失败后触发 成本低,拦截基础脚本 可被打码平台绕过
短信验证码 注册、登录、找回密码、敏感操作 强身份校验 短信成本高,重点防刷
邮件验证码 后台账号、B端、找回密码 成本低 邮箱可批量注册
行为验证(极验/阿里云人机验证) 高风险接口,登录、活动提交 识别脚本行为,抗打码更强 第三方服务,有费用

推荐组合:滑块人机验证 + 短信验证码,不要只用短信验证码作为唯一防护。

3.2 验证码业务规则(可直接写进代码)

3.2.1 短信验证码规则
  1. 验证码长度:6位数字,有效期5分钟。
  2. 同一手机号:1分钟最多1次,1小时最多5次,24小时最多10次。超出直接拒绝,不返回"验证码已发送",避免被遍历手机号。
  3. 验证码校验错误:连续3次错误直接失效,需要重新获取。
  4. 验证码只能使用一次,验证成功后立即删除/标记已使用,不可重复复用。
  5. 禁止返回详细错误信息:
    • ❌ 不要返回:手机号不存在 / 验证码错误 / 验证码过期
    • ✅ 统一返回:验证码错误或已失效
  6. 发送前前置校验:先过滑块人机验证,再允许发送短信(关键!防止直接刷短信接口)。

接口逻辑伪代码:

复制代码
获取短信验证码接口
1. 校验请求参数合法性(手机号格式)
2. 网关限流校验
3. 校验前端传入的人机验证ticket,调用第三方验证接口,验证失败直接返回拒绝
4. 查询该手机号发送计数:1min/1h/24h超限 → 返回请求频繁
5. 生成6位验证码,存入Redis,key=phone:xxx,value=code,expire=5min
6. Redis同时记录发送计数器:phone:send:cnt,1h、24h两个计数器
7. 调用短信通道发送
8. 返回成功(不返回验证码)
3.2.2 图形/滑块验证码规则
  1. 验证码有效期:2分钟,一次ticket只能使用一次,校验成功即作废。
  2. 同一IP短时间多次获取验证码,直接锁定,一段时间内不能刷新。
  3. 前端禁止把验证码key/ticket暴露在可被批量抓取的地方;前端增加简单延时,禁止高频点击刷新。

3.3 验证码安全注意点

  1. 验证码不能在前端生成,全部后端生成、后端校验。
  2. 禁止前端缓存验证码结果。
  3. 接口必须校验请求来源(Referer)+ 前端token/设备指纹,防止直接裸调用后端接口。
  4. 短信模板增加防刷提示,限制同一号码大量接收。

4. 接口防刷策略(核心)

防刷分为:IP限流、账号限流、设备指纹、风控规则、黑名单,全部使用Redis实现,高性能。

4.1 限流规则(可直接配置)

4.1.1 IP维度限流(网关优先)
  • 通用接口:单IP 100次/分钟
  • 验证码发送接口:单IP 5次/分钟,30次/小时

超过阈值,直接返回429 请求过于频繁,不进入业务逻辑。
Redis限流key示例:limit:ip:192.168.1.1,采用滑动窗口限流,优于固定窗口。

4.1.2 账号/手机号维度限流
  • 登录接口:同一账号,10次/小时,连续5次密码错误 → 锁定账号15分钟,锁定期间禁止登录。
  • 短信发送:前面3.2.1已定义:1次/分钟,5次/小时,10次/24h。
4.1.3 设备指纹限流

采集设备特征(UA、屏幕分辨率、浏览器插件、客户端随机设备ID,不要采集隐私信息 ),生成设备指纹hash。

同一设备指纹,短时间高频请求,判定异常,触发人机验证。

注意:设备指纹仅做风控,不做唯一身份识别,避免合规风险。

4.2 黑名单机制

黑名单分两类:IP黑名单、账号黑名单

  1. 临时黑名单 :触发阈值后,封禁一段时间(10分钟 ~ 24小时),自动释放。
    • 例如:IP 1小时内短信请求超过30次 → 加入黑名单1小时。
  2. 永久黑名单:人工运营+风控识别,持续恶意攻击IP/账号,人工加入,需后台手动解除。
  3. 黑名单存储在Redis,网关层优先拦截黑名单,不进业务服务。

4.3 行为风控规则(业务层判断)

满足下面任意一条,强制弹出人机验证,严重直接拦截:

  1. 短时间大量不同手机号,从同一个IP请求验证码。
  2. 同一设备指纹,短时间切换大量手机号。
  3. 账号异地登录,IP归属地和历史常用地区差异大。
  4. 请求UA异常(无UA、爬虫特征UA、大量相同UA)。
  5. 请求间隔极短,小于人类正常操作间隔(比如连续请求间隔<300ms)。

风控结果不直接拒绝,分级:

  • 低风险:正常放行
  • 中风险:强制人机验证
  • 高风险:直接拒绝请求,加入临时黑名单

4.4 代理IP识别增强

  • 识别代理、机房IP(第三方IP库),机房IP直接提高风控等级,默认强制人机验证。
  • 检测X-Forwarded-For,判断是否多层代理。

5. 分层防护策略

5.1 CDN / WAF / 网关层(Nginx/Ingress/ApiGateway)

第一层,在请求到达应用服务器之前拦截

  1. WAF:拦截常见攻击特征(SQL注入、xss、恶意爬虫特征)。
  2. 网关IP限流,滑动窗口,超出直接返回429。
  3. 黑名单IP直接丢弃,不转发到后端。
  4. 限制单IP并发连接数。
  5. 拦截非法请求头、异常请求。

优点:减轻后端压力,恶意流量在入口就干掉。

5.2 应用层(SpringBoot/Node等后端服务)

  1. 接口鉴权:未登录接口校验token/设备标识。
  2. 滑动窗口限流(Redis+Lua脚本,保证原子性,防止超量)。
  3. 设备指纹校验,行为风控。
  4. 验证码ticket校验。

推荐Lua脚本实现限流,避免并发下计数不准。

5.3 业务层

  1. 业务计数:手机号24h发送上限。
  2. 账号登录失败锁定。
  3. 业务逻辑校验:比如注册,一个手机号只能注册1个账号。
  4. 敏感操作二次验证(修改密码、绑定手机号,必须短信验证码)。

6. 数据埋点与告警

6.1 埋点日志字段

所有验证码/登录接口请求,必须记录日志:

  • 请求时间、客户端IP、IP归属地、设备指纹、手机号、接口名称、返回码、是否触发验证码、是否被限流、是否命中黑名单。

日志存储:ELK / 日志服务,保留至少7天。

6.2 告警规则(对接监控平台,如Prometheus+Grafana/云监控)

触发告警,通知开发/运维:

  1. 短信接口QPS突增,超过基线2倍。
  2. 接口429限流错误占比 >5%。
  3. 黑名单新增IP数量突增。
  4. 短信发送失败率异常升高。

7. 降级与用户体验策略

防刷不能牺牲正常用户体验,默认不弹验证码,异常才弹。

  1. 正常用户:正常访问,不弹出滑块验证码。
  2. 轻度异常:弹出滑块人机验证,验证通过后继续业务。
  3. 重度异常:直接返回请求频繁,拒绝访问。
  4. 第三方人机验证服务不可用时:降级策略,切换为图形验证码;不可用时,可临时提高限流阈值,不能直接关闭防刷。
  5. 提示文案友好:
    • ✅ 操作过于频繁,请稍后重试
    • ❌ 不要写:检测到你是爬虫

8. 部署与上线步骤

  1. 开发阶段:
    • 实现Redis滑动窗口限流、黑名单、验证码存储逻辑。
    • 接入第三方人机验证(滑块)。
    • 编写Lua限流脚本。
  2. 测试环境:
    • 压测、脚本模拟爬虫刷接口,验证限流、黑名单、验证码拦截效果。
  3. 灰度上线:
    • 先开放10%流量,观察监控告警,调整阈值。
    • 逐步全量上线。
  4. 上线后:持续观察短信量、接口429数量,调整阈值。

9. 测试用例

测试场景 预期结果
同一手机号1分钟内连续请求短信2次 第二次返回请求频繁
同一IP高频调用短信接口 触发限流,返回429
不携带人机验证ticket直接调用短信接口 直接拒绝
验证码使用一次后再次提交 提示验证码错误或失效
连续5次密码错误登录 账号锁定15分钟
机房代理IP访问 强制弹出人机验证
正常用户正常操作 无验证码,正常使用

10. 运维与迭代

  1. 定期更新机房IP库,优化代理IP识别。
  2. 定期复盘攻击日志,调整风控规则和限流阈值。
  3. 定期演练:模拟爬虫刷接口,验证防刷链路是否失效。
  4. 定期评估第三方人机验证服务商,评估被打码平台绕过风险。
  5. 安全扫描:每季度渗透测试,测试验证码绕过、接口裸调用漏洞。

附录:Redis滑动窗口限流Lua脚本(参考)

lua 复制代码
-- key: 限流key,如 limit:ip:xxx
-- window: 窗口大小,单位秒
-- limit: 最大允许次数
local key = KEYS[1]
local window = tonumber(ARGV[1])
local limit = tonumber(ARGV[2])
local now = tonumber(ARGV[3])

-- 移除窗口外过期数据
redis.call('ZREMRANGEBYSCORE', key, 0, now - window)
-- 统计当前窗口数量
local count = redis.call('ZCARD', key)
if count < limit then
    -- 存入当前时间戳
    redis.call('ZADD', key, now, now .. ':' .. math.random())
    redis.call('EXPIRE', key, window)
    return 1
else
    return 0
end

返回1=允许访问;返回0=限流拒绝。


补充:安全红线(禁止做)

  1. ❌ 只靠验证码做唯一防护,不做限流。
  2. ❌ 前端直接校验验证码,后端不二次校验。
  3. ❌ 错误信息返回过于详细,方便攻击者枚举。
  4. ❌ 验证码长期有效,不做一次性销毁。
  5. ❌ 关闭日志,不做监控告警。

相关推荐
奋进小青1 小时前
2026年CNN与Transformer融合的创新点思路
人工智能·cnn·transformer
阿文和她的Key1 小时前
DeepInfer 与 TorchTPU 同日开源:供应商锁定的成本结构正在被重写
网络·人工智能·架构·开源
lucas_AI1 小时前
AI 阅卷的第一道坎:学生涂改的叉,模型读成了答案
人工智能
AI Workforce1 小时前
数据质量:4 层去重 + 黑名单机制——宁可漏杀,不可错杀
大数据·人工智能·ai·架构·prompt
中烟创新1 小时前
中烟创新×某烟草公司 | 企业综合管理平台:从“系统林立”到“一个平台”
人工智能·深度学习·中烟创新
进击的雷神1 小时前
怕 AI Agent 乱删文件?Tank-OS 把它锁进不可变系统
人工智能·ai·api·agent
lucas_AI1 小时前
用 AI 复读公元前 3 世纪的石碑:阿育王铭文从风化岩石直通英译
人工智能
lucas_AI1 小时前
页都塞给模型了,它还是答错:哈工大实测 VLM『拿着证据不用』有多离谱
人工智能
Fxkj8881 小时前
佛山企业做小程序:模板定制与源码定制怎么选?
人工智能·小程序