如何解决短信验证码接口被狂刷导致系统崩溃的问题?


一、背景

短信验证码功能我们都不陌生,我们印象中的短信验证码都是有发送限制的(如60s内只能发送1次),这样做的目的一方面是为了保护系统,另一方面也是为了控制成本(发短信要钱的)。

我们先简单分析一下短信验证码接口被狂刷的主要场景有哪些:

  • 同一用户id狂刷
  • 同一ip狂刷(也就是用不同用户id狂刷)
  • 所有用户id都狂刷

二、解决方案

要解决上面提到的问题,我们大概思路可以分为限流缓存安全

限流方案可以分为以下几种:

  • 客户端限制用户频繁发送:如按钮置灰防止用户频繁点击
  • 服务端限制用户频繁发送客户端限制用户频繁发送的方案可能会被绕过,所以我们需要双重保证,通过记录上次发送时间点来判断是否在60s内发送过(可以配置多重策略,如60s只能发送1次、24h只能发送10次等
  • ip限流:可以通过滑动窗口算法来记录同一个ip在短时间内发送的短信验证码条数,来达到限制不同用户id狂刷的问题(即上面两种方案)
  • 验证码缓存:一些安全性不高的场景(如绑定手机等,其他敏感场景如银行转账等则不适用)可以采用验证码缓存的方式,在短时间内重复请求会返回已缓存的验证码(即多次发也只能生成1条短信)
  • token校验:将短信验证码接口加上token校验,每次请求都需要携带服务端返回的唯一token标识才能正常响应
  • 动态黑名单:可以通过一些算法将疑似恶意刷接口的用户/ip给添加到黑名单,限制他们的接口请求(也可能出现误封,需要提供手动解封的功能)

三、Q&A

1、每天只能发送10次的限制要按自然日还是过去24小时?

正常来说是按过去24小时,因为如果是自然日的话,可能会出现23:59:59发送了10条短信,而00:00:00又发送了10条短信,可能会出现性能瓶颈等问题。

2、如何实现滑动窗口算法?

// 大概思路是使用Redis的Zset数据结构,因为考虑到它的速度快和有序(可用来存时间戳)


文章作者: GaryLee
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 GaryLee !
  目录