在大多数系统中,短信验证码通常被视为一个"基础功能":
注册要用,登录要用,找回密码也要用。
但在真实运行环境里,短信验证码往往是最容易被攻击、同时最容易被低估的系统入口之一。
本文不讨论如何接入短信服务,也不讨论验证码格式,而是从系统安全设计 的角度,给出一套短信风控设计规范供参考。
一、短信验证码的系统风险定位
在安全设计中,第一步永远不是"怎么防",而是"它是什么"。
从系统视角看,短信验证码接口同时具备以下特征:
- 对公网开放
- 不依赖登录态
- 可被高频调用
- 每次调用都产生真实成本
这意味着它不是普通业务接口,而是一个成本型风险入口。
任何设计短信验证码的系统,都必须默认一个前提:
这个接口一定会被攻击。
二、核心设计原则
原则一:短信发送不是功能动作,而是风险决策
短信验证码的本质不是"发送成功",而是"是否值得发送"。
因此,短信发送必须满足以下约束:
- 任何发送行为都必须先经过风控评估
- 评估失败属于业务拒绝,而非系统异常
- 不存在绕过风控直接发送的路径
原则二:风控判断必须基于行为,而非单次请求
一次请求无法说明问题,行为模式才是风控判断的核心依据。
系统必须具备对以下行为的识别能力:
- 高频或持续请求
- 请求成功率异常偏低
- 只请求、不校验的行为模式
- 短时间内频繁更换请求身份
原则三:风控逻辑必须独立于具体业务模块
短信风控是横向安全能力,不应被埋在:
- 用户模块
- 登录流程
- Controller 逻辑中
风控系统应以独立组件或服务存在,由业务模块调用并消费风控结果。
三、风控输入数据规范
1. 必须采集的基础数据
- 手机号(建议脱敏存储)
- 请求场景(注册 / 登录 / 找回密码等)
- 请求时间戳
- 请求 IP
- User-Agent
2. 推荐采集的弱身份信息
- 设备标识(deviceId)
- 请求来源(Web / App / 小程序等)
- 会话标识(如存在)
风控判断应基于多维信息组合,而非依赖单一身份。
四、风控评估维度设计
1. 时间与频率维度
- 单位时间内请求次数
- 请求间隔是否异常稳定
- 是否存在长时间持续请求行为
2. 身份维度
- 同手机号请求行为
- 同设备请求行为
- 同 IP 请求行为
- 不同身份之间的关联性
3. 场景维度
不同业务场景应具备不同风控策略:
- 注册:中风险
- 登录:中风险
- 找回密码 / 修改敏感信息:高风险
禁止所有场景共用一套完全一致的风控规则。
五、风控决策与执行规范
1. 决策时序
风控评估 必须在短信发送之前完成。
任何事后风控都无法挽回已经发生的成本消耗。
2. 决策结果类型
风控结果应至少支持以下类型:
- 放行
- 冷却(延迟发送)
- 拒绝发送
风控拒绝需返回统一、克制的业务提示,不暴露内部规则细节。
3. 状态与恢复机制
- 风控状态应支持自动过期
- 不同维度的风控状态可独立恢复
- 禁止永久性封禁作为默认策略
六、工程实现规范
1. 架构建议
- 风控逻辑封装为独立组件或服务
- 业务模块仅消费风控结果
- 风控规则可配置、可调整
2. 状态存储
- 需支持高并发读写
- 支持时间窗口统计
- 支持行为累计
七、日志、审计与追溯
系统必须记录以下信息:
- 每一次风控决策结果
- 触发风控的主要原因(内部使用)
- 可按手机号 / IP / 设备追溯行为轨迹
日志不应影响主流程性能。
八、异常与降级策略
- 风控拒绝不应返回系统错误
- 风控组件异常时,必须有明确降级策略
- 禁止在风控失效时默认无条件放行
九、明确不做的事情
为保持系统可维护性,建议明确以下边界:
- 不追求 100% 防刷
- 不强依赖复杂模型或第三方风控
- 不将风控规则写死在业务代码中
- 不在早期阶段过度设计
十、结语
短信验证码并不是一个"小功能"。
它是一个一旦失控,就会直接造成真实损失的系统入口。
在系统设计阶段给予它足够的安全权重,
不是过度设计,而是对真实运行环境的尊重。