Redis如何实现验证码发送 以及限制每日发送次数


Posted in Redis onApril 18, 2022

1、功能

  • 输入手机号,点击发送后随机生成六位数字码,2分钟有效
  • 输入验证码,点击验证,返回成功或失败
  • 每个手机号每天只能输3次

2、分析

  • 每个手机每天只能输3次:incr每次发送之后+1,当值为3时提示不能发送,过期时间为当天结束
  • 随机生成6位数字验证码:RandomUtil(hutool)
  • 验证码2分钟有效:放入redis里并设置过期时间2分钟
  • 判断验证码是否一致:从redis里获取验证码和输入的验证码进行比对

3、实现

package cn.ken.blog.controller.common;

import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.RandomUtil;
import cn.ken.blog.common.constant.Constants;
import cn.ken.blog.common.domain.Result;
import cn.ken.blog.common.enums.ErrorCodeEnum;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.util.ObjectUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.Date;
import java.util.concurrent.TimeUnit;

/**
 * 验证码控制器
 * @author Ken-Chy129
 * @date 2022/4/17 20:28
 */
@RestController
@SuppressWarnings(value = { "unchecked", "rawtypes" })
public class CaptureController {
    
    @Autowired
    private RedisTemplate redisTemplate;
    
    // 生成验证码
    @GetMapping("getNumCode")
    public Result<String> getNumCode(String phone) {
        String captureLimitKey = Constants.CAPTCHA_LIMIT_KEY + phone;
        Integer counts = (Integer) redisTemplate.opsForValue().get(captureLimitKey);
        if (ObjectUtils.isEmpty(counts)) {
            // 今天第一次验证,故之前缓存中无该键
            // 距离今天结束剩下多少毫秒
            long expire = DateUtil.endOfDay(new Date()).between(new Date(), DateUnit.MS);
            redisTemplate.opsForValue().set(captureLimitKey, 1, expire, TimeUnit.MILLISECONDS);
        } else if (counts < 3) {
            // 没有超过限制次数
            redisTemplate.opsForValue().increment(captureLimitKey);
        } else {
            // 超过限制次数,不生成验证码,直接返回
            return new Result<String>().error(ErrorCodeEnum.OVER_LIMITS);
        }
        // 生成验证码
        String code = RandomUtil.randomNumbers(6); // 随机生成六位数
        String captureCodeKey = Constants.CAPTCHA_CODE_KEY + phone;
        redisTemplate.opsForValue().set(captureCodeKey, code, Constants.CAPTCHA_EXPIRATION, TimeUnit.MINUTES);
        return new Result<String>().success(captureCodeKey + ":" + code);
    }
    
    // 验证验证码
    @GetMapping("verify")
    public Result<String> verify(String phone, String code) {
        String captureCodeKey = Constants.CAPTCHA_CODE_KEY + phone;
        String realCode = (String) redisTemplate.opsForValue().get(captureCodeKey);
        if (ObjectUtils.isEmpty(realCode)) {
            // redis中不存在该用户生成的验证码,证明验证码以过期销毁
            return new Result<String>().error(ErrorCodeEnum.OVERDUE_CODE);
        }
        if (realCode.equals(code)) {
            return new Result<String>().success("验证成功");
        } else {
            return new Result<String>().error(ErrorCodeEnum.ERROR_CODE);
        }
    }
    
//    @Scheduled(cron = "0 0 12 * * ?")
//    private void clear() {
//        redisTemplate.delete()
//    }
}
// Constants类

/**
 * 验证码 redis key
 */
public static final String CAPTCHA_CODE_KEY = "captcha_codes:";

/**
 * 每日限制 redis key
 */
public static final String CAPTCHA_LIMIT_KEY = "captcha_limits:";
/**
 * 验证码有效期(分钟)
 */
public static final Integer CAPTCHA_EXPIRATION = 2;

到此这篇关于Redis实现验证码发送并限制每日发送次数的示例代码的文章就介绍到这了!

Redis 相关文章推荐
redis配置文件中常用配置详解
Apr 14 Redis
redis三种高可用方式部署的实现
May 11 Redis
Redis延迟队列和分布式延迟队列的简答实现
May 13 Redis
详解缓存穿透击穿雪崩解决方案
May 28 Redis
详解Redis复制原理
Jun 04 Redis
k8s部署redis cluster集群的实现
Jun 24 Redis
Redis分布式锁Redlock的实现
Aug 07 Redis
使用Redis实现点赞取消点赞的详细代码
Mar 20 Redis
Redis 哨兵机制及配置实现
Mar 25 Redis
redis sentinel监控高可用集群实现的配置步骤
Apr 01 Redis
浅谈Redis变慢的原因及排查方法
Jun 21 Redis
Redis Lua脚本实现ip限流示例
Jul 15 Redis
Redis实战高并发之扣减库存项目
Redis中key的过期删除策略和内存淘汰机制
解决 Redis 秒杀超卖场景的高并发
redis 解决库存并发问题实现数量控制
Redis超详细讲解高可用主从复制基础与哨兵模式方案
redis复制有可能碰到的问题汇总
Apr 03 #Redis
 Redis 串行生成顺序编码的方法实现
You might like
一个php作的文本留言本的例子(二)
2006/10/09 PHP
php抓取https的内容的代码
2010/04/06 PHP
PHP中使用mktime获取时间戳的一个黑色幽默分析
2012/05/31 PHP
解析php中两种缩放图片的函数,为图片添加水印
2013/06/14 PHP
PHP 快速排序算法详解
2014/11/10 PHP
PHPStrom中实用的功能和快捷键大全
2015/09/23 PHP
Yii2搭建后台并实现rbac权限控制完整实例教程
2016/04/28 PHP
PHP实现将上传图片自动缩放到指定分辨率,并保持清晰度封装类示例
2019/06/17 PHP
js cookies 常见网页木马挂马代码 24小时只加载一次
2009/04/13 Javascript
解析jquery中的ajax缓存问题
2013/12/19 Javascript
JS实现自动定时切换的简洁网页选项卡效果
2015/10/13 Javascript
Web前端新人笔记之jquery入门心得(新手必看)
2016/05/17 Javascript
BootStrap CSS全局样式和表格样式源码解析
2017/01/20 Javascript
JavaScript实现多重继承的方法分析
2018/01/09 Javascript
一个Java程序猿眼中的前后端分离以及Vue.js入门(推荐)
2019/04/19 Javascript
微信小程序实现跳转的几种方式总结(推荐)
2019/04/24 Javascript
layer弹出层取消遮罩的方法
2019/09/25 Javascript
jquery传参及获取方式(两种方式)
2020/02/13 jQuery
Js跳出两级循环方法代码实例
2020/09/22 Javascript
Python实现Tab自动补全和历史命令管理的方法
2015/03/12 Python
pandas or sql计算前后两行数据间的增值方法
2018/04/20 Python
django允许外部访问的实例讲解
2018/05/14 Python
Python使用pickle模块报错EOFError Ran out of input的解决方法
2018/08/16 Python
python自动发送测试报告邮件功能的实现
2019/01/22 Python
pytorch中如何使用DataLoader对数据集进行批处理的方法
2019/08/06 Python
Python xlrd/xlwt 创建excel文件及常用操作
2020/09/24 Python
Canvas获取视频第一帧缩略图的实现
2020/11/11 HTML / CSS
面料业务员岗位职责
2013/12/26 职场文书
幼儿园教研活动方案
2014/01/19 职场文书
高中军训感言500字
2014/02/24 职场文书
学习优秀党务工作者先进事迹材料思想报告
2014/09/17 职场文书
公民授权委托书范本
2014/09/17 职场文书
财务经理岗位职责范本
2015/04/08 职场文书
2016小学优秀教师先进事迹材料
2016/02/26 职场文书
2016年幼儿园教师师德承诺书
2016/03/25 职场文书
简单谈谈Python面向对象的相关知识
2021/06/28 Python