Redis实现短信验证码

该文章介绍了如何利用Redis来实现短信验证码的发送限制,包括1分钟内不允许重复发送和每天最多发送10条的规则。通过设置两个不同的Rediskey,phone-code用于记录验证码并设置1分钟有效期,phone-count用于计数每日发送的短信数量,并设置一天的有效期。当达到限制时,系统将阻止发送并返回相应错误信息。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

利用Redis实现存储短信验证码

  • 要求需要限制短信在1分钟之内不能再次发送
  • 要求短信一天之内的发送的短信条数限制10条

思路

  • 需要两个缓存
  • key名称为phone-code,缓存1分钟
  • key名称为phone-count,缓存1天,每成功发送一条+1
  • 流程:
  1. 判断phone-code是否存在,存在直接报错,“短信发送频繁,请1分钟之后再试”
  2. 判断phone-count是否存在,存在则继续检测是否等于10,存在且等于10报错,“您今天的发送次数超过10次”
  3. 发送短信
  4. 写入phone-code,有效期1分钟
  5. 写入phone-count,有效期当天23:59:59的时间戳-当前时间戳

实现

短信接口
@RequestMapping(value = "phoneMsg")
public  Object sendXCXDuanxin(HttpServletRequest request,@RequestParam Map  map) throws ParseException {

//判断参数phone
String phone = map.containsKey("phone") ? String.valueOf(map.get("phone")) :  null;

//定义Redis变量名
String Count="phone-count:"+phone;
String Code="phone-code:"+phone;

//判断对应的key是否存在
//存在则获取对应的value,否则为“”
String isRedis =redisTemplate.hasKey(Code)?String.valueOf(redisTemplate.opsForValue().get(Code)):"";
//判断是否不为“”
if (!"".equals(isRedis)){
   return Results.failure("短信发送频繁,请一分钟后再试!");
}

if ("10".equals(redisTemplate.opsForValue().get(DuanxinCount))){
   return Results.failure("该手机号收发短信已达上限");
}

//存入缓存
//设置有效时长为1分钟
redisTemplate.opsForValue().set(Code,verifyCode,1L,TimeUnit.MINUTES);

//判断
if (redisTemplate.opsForValue().get(Count)==null){   redisTemplate.opsForValue().set(Count,"1",getEndTime(),TimeUnit.MILLISECONDS);
}else {
   String value = redisTemplate.opsForValue().get(Count).toString();
   int times = Integer.parseInt(value) + 1;
   String timesStr = String.valueOf(times);
   //有效期截止到当天晚上
   redisTemplate.opsForValue().set(Count,timesStr,getEndTime(),TimeUnit.MILLISECONDS);
}
}
//获取当前时间到今天结束时间所剩余的毫秒数:
public static long getEndTime() {
   //获取当前时间的毫秒数
   long time = new java.util.Date().getTime();
   //获取到今天结束的毫秒数
   Calendar todayEnd = Calendar.getInstance();
   todayEnd.set(Calendar.HOUR_OF_DAY, 23); // Calendar.HOUR 12小时制。HOUR_OF_DAY 24小时制
   todayEnd.set(Calendar.MINUTE, 59);
   todayEnd.set(Calendar.SECOND, 59);
   todayEnd.set(Calendar.MILLISECOND, 999);
   long endTime = todayEnd.getTimeInMillis();
   //这里endTime-time获取的是到23:59:59:999的毫秒数。再加1才是到24点整的毫秒数
   return endTime-time+1;
}
实现2.0
//定义redis key的name
String DuanxinCountByDay="phone-send-day:"+phone;

//判断是否有对应的key
Integer counts=redisTemplate.hasKey(DuanxinCountByDay)?Integer.valueOf(redisTemplate.opsForValue.get(DuanxinCountByDay).toString()):null;


if(counts==null){
    //今天第一次验证,故之前缓存中无该键
    //距离今天结束剩下多少毫秒
    Calendar calendar =Calendar.getInstance();
    DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    calendar.set(Calendar.MILLISECOND,0);
    calendar.set(Calendar.SECOND,0);
    calendar.set(Calendar.MINUTE, 0);
    calendar.set(Calendar.HOUR_OF_DAY, 0);
    calendar.add(Calendar.DAY_OF_MONTH, 1);

    long expire=(calendar.getTimeInMillis()-System.currentTimeMillis())/1000;

redisTemplate.opsForValue().set(DuanxinCountByDay,1,expire,TimeUnit.SECONDS);
}else if(counts < 3){
    //没有超过限制次数
    redisTemplate.opsForValue().increment(DuanxinCountByDay,1);
}else{
    //超过限制次数,不生成验证码,直接返回
    return Results.failure("已超过当天短信发送次数");
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值