登录验证码发送间隔限制的设计与实现
引言
在小项目设计登录模块时,一个常见的思路是账号与邮箱/手机号绑定,通过邮件/短信验证码的方式登录/注册。相比于传统的口令式注册/登录有以下优点:
- 用户不需要记住密码:只要邮箱/手机号还能用,就可以登录。
- 系统不需要考虑太多安全问题:数据库不存储敏感信息,安全性由邮箱/电信运营商保障。
- 登录、注册合一:简化开发。
发送邮件/短信验证码一般都要通过云厂商的服务来实现,如果有人恶意刷接口就会产生大量费用。而且登录验证码本身也是一段时间内有效的,不需要频繁调用。所以我们需要对发送验证码的接口做调用时间间隔的限制。
本文用 vue3 + element plus + springboot 的技术栈举例。重点在分享思路,在使用其他技术栈的情况下也可以套用。
后端
目的:对于同一个邮箱来说,一分钟内最多发送一次验证码。
思路:使用 Caffeine 库的 Cache 类,过期策略是写后 1 分钟过期。key 存放邮箱,value 存一个 new Object()
(我们可以称之为 timer)。发送验证码之前先检查 cache 里邮箱对应的 timer 是否还在,如果还在说明 1 分钟内发过验证码,拒绝重复发送;如果不在就可以发。
实现:
/**
* 登录验证码缓存, 5 分钟有效期
*/
private final Cache<String, String> loginCodeCache = Caffeine.newBuilder().expireAfterWrite(5, TimeUnit.MINUTES).build();
/**
* 限制用户发送登录验证码的时间间隔, 如果缓存还在, 说明