利用Redis实现存储短信验证码
- 要求需要限制短信在1分钟之内不能再次发送
- 要求短信一天之内的发送的短信条数限制10条
思路
- 需要两个缓存
- key名称为phone-code,缓存1分钟
- key名称为phone-count,缓存1天,每成功发送一条+1
- 流程:
- 判断phone-code是否存在,存在直接报错,“短信发送频繁,请1分钟之后再试”
- 判断phone-count是否存在,存在则继续检测是否等于10,存在且等于10报错,“您今天的发送次数超过10次”
- 发送短信
- 写入phone-code,有效期1分钟
- 写入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("已超过当天短信发送次数");
}