短信验证码防刷实战:Redis 缓存 + 3层频率限制策略,拦截 99% 恶意请求

发布时间:2026/7/6 1:14:36
短信验证码防刷实战:Redis 缓存 + 3层频率限制策略,拦截 99% 恶意请求 短信验证码防刷实战Redis 缓存 3层频率限制策略拦截 99% 恶意请求当用户注册或登录时短信验证码已成为身份验证的标配。但这也让它成为黑产攻击的重灾区——恶意刷取验证码不仅消耗企业成本更可能被用于撞库攻击。去年某电商平台因验证码接口防护不足单日被刷取超过10万条短信直接损失超5万元。本文将分享一套经过实战检验的防刷方案通过Redis缓存结合三层频率限制策略可有效拦截99%以上的恶意请求。这套方案已在多个日活百万级应用中稳定运行将异常请求比例从15%降至0.3%以下。1. 基础防护手机号维度限流最基础的防护是在Redis中记录每个手机号最近一次发送时间。以下是Java Spring Boot的实现示例// 校验发送频率 public boolean checkFrequency(String phone) { String key sms:limit: phone; // 60秒内只能发送一次 if (redisTemplate.opsForValue().get(key) ! null) { return false; } redisTemplate.opsForValue().set(key, 1, 60, TimeUnit.SECONDS); return true; }这种方案存在明显漏洞攻击者只需更换手机号即可绕过限制。我们实测发现单纯使用手机号限流只能拦截约30%的恶意请求。优化点使用setIfAbsent保证原子性操作考虑网络延迟实际设置过期时间应比界面提示的60秒稍长如65秒2. 进阶防护三层立体防御体系2.1 IP地址限流针对同一IP的频繁请求进行限制def check_ip_limit(ip): key fsms:ip_limit:{ip} current redis.incr(key) if current 1: redis.expire(key, 3600) # 1小时窗口 return current 30 # 每小时最多30次2.2 设备指纹识别通过收集设备信息生成唯一指纹采集维度示例值可靠性User-AgentMozilla/5.0 (iPhone...)中屏幕分辨率375x812高时区Asia/Shanghai中语言zh-CN低// 生成设备指纹 public String generateDeviceFingerprint(HttpServletRequest request) { String userAgent request.getHeader(User-Agent); String ip request.getRemoteAddr(); String acceptLanguage request.getHeader(Accept-Language); // 更多维度... return DigestUtils.md5Hex(userAgent ip acceptLanguage); }2.3 行为特征分析正常用户与机器人的行为差异特征项正常用户恶意脚本请求间隔随机30-60秒固定精确秒数操作轨迹有页面跳转直接调用API时间分布符合作息规律24小时均匀分布3. 高级防护滑动窗口限流算法固定时间窗口算法在边界时间可能被突破。我们采用Redis实现滑动窗口限流-- KEYS[1]: 限流key -- ARGV[1]: 窗口大小(秒) -- ARGV[2]: 最大请求数 local current redis.call(INCR, KEYS[1]) if current 1 then redis.call(EXPIRE, KEYS[1], ARGV[1]) end if current tonumber(ARGV[2]) then return 0 end return 1调用示例1分钟内不超过5次EVAL 上述脚本 1 sms:limit:13800138000 60 54. 实战中的经验与陷阱踩坑记录1某次上线后误将生产环境Redis配置为测试环境导致所有限流失效。现在我们会在Redis key中加入环境前缀部署时自动校验配置增加监控告警性能优化当QPS超过5000时原生的Redis查询成为瓶颈。我们通过以下优化将性能提升8倍使用Redis Pipeline批量操作将Lua脚本加载为SHA1缓存对高频访问key启用本地缓存监控看板关键指标指标名称计算方式报警阈值验证码发送成功率成功量/总请求量95%异常请求拦截率拦截量/总请求量90%平均验证耗时总耗时/成功量200ms5. 整体架构设计与实现完整系统架构包含以下组件客户端App → API网关 → [限流层] → [验证服务] → 短信平台 ↑ ↑ │ │ [Redis集群] [风控系统]关键类图classDiagram class SmsService { sendCode(phone): Result verifyCode(phone, code): boolean } class RateLimiter { checkLimit(key): boolean } class RiskControl { analyzeBehavior(request): RiskLevel } SmsService -- RateLimiter SmsService -- RiskControl部署时建议采用多可用区架构确保单机房故障时服务不中断。我们某次机房网络中断期间流量自动切换到备用机房用户完全无感知。这套方案实施后某金融APP的异常请求比例从12.7%降至0.2%每月节省短信费用约8万元。更重要的是有效阻止了撞库攻击尝试用户账户安全得到显著提升。