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

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

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

版本: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. ❌ 关闭日志,不做监控告警。

相关推荐
硅谷秋水4 分钟前
PhysicalWords:一种用于构建机器人操作中潜推理过程的词汇体系
人工智能·机器学习·计算机视觉·语言模型·机器人
喵个咪26 分钟前
GoWind 拆解:AI Agent 编排引擎——波次并行、子图递归与人工审批
人工智能·后端·go
Shanks.1 小时前
2026 远程控制软件实测:ToDesk / 向日葵 / RustDesk / TeamViewer 在跨城与弱网下的真实差距
网络·远程工作·软件需求
ZzT1 小时前
AI 是放大器:基础越扎实,放大效果越明显
人工智能·ai编程
喵个咪1 小时前
GoWind Admin 拆解:AI 能力层——工具循环、pgvector 知识库与机器凭证
人工智能·后端·agent
老金带你玩AI1 小时前
10秒出4K,MiniMax还开源了!H3 Image上线!
人工智能
mantou1322 小时前
只用 Cloudflare 全家桶,给游戏站做一个 RAG 搜索和问答
人工智能·llm
AI前端工程狮2 小时前
服务端已经死了,客户端却报"超时"
人工智能·程序员
阿屿2 小时前
从零手搓 AI 伴侣(二):好感度通胀危机,与它的「货币政策」
java·人工智能
Jeremy_WW2 小时前
802.3协议解读 06:117章节 RS 和 200GMII / 400GMII I
网络·网络协议·信息与通信·光模块·802.3协议