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 12 Redis
Redis安装启动及常见数据类型
Apr 14 Redis
Redis5之后版本的高可用集群搭建的实现
Apr 27 Redis
Redis实现订单自动过期功能的示例代码
May 08 Redis
Redis 哨兵集群的实现
Jun 18 Redis
厉害!这是Redis可视化工具最全的横向评测
Jul 15 Redis
Redis中一个String类型引发的惨案
Jul 25 Redis
使用redis实现延迟通知功能(Redis过期键通知)
Sep 04 Redis
Redis高并发防止秒杀超卖实战源码解决方案
Nov 01 Redis
解决redis批量删除key值的问题
Mar 23 Redis
Redis keys命令的具体使用
Jun 05 Redis
Redis配置外网可访问(redis远程连接不上)的方法
Dec 24 Redis
Redis实战高并发之扣减库存项目
Redis中key的过期删除策略和内存淘汰机制
解决 Redis 秒杀超卖场景的高并发
redis 解决库存并发问题实现数量控制
Redis超详细讲解高可用主从复制基础与哨兵模式方案
redis复制有可能碰到的问题汇总
Apr 03 #Redis
 Redis 串行生成顺序编码的方法实现
You might like
php快速查找数据库中恶意代码的方法
2015/04/01 PHP
JavaScript confirm选择判断
2008/10/18 Javascript
safari,opera嵌入iframe页面cookie读取问题解决方法
2010/06/23 Javascript
jquery实现带单选按钮的表格行选中时高亮显示
2013/08/01 Javascript
node中socket.io的事件使用详解
2014/12/15 Javascript
28个常用JavaScript方法集锦
2015/01/14 Javascript
JavaScript返回0-1之间随机数的方法
2015/04/06 Javascript
javascript设计简单的秒表计时器
2020/09/05 Javascript
JS中判断字符串中出现次数最多的字符及出现的次数的简单实例
2016/06/03 Javascript
Angularjs根据json文件动态生成路由状态的实现方法
2017/04/17 Javascript
在 Node.js 中使用原生 ES 模块方法解析
2017/09/19 Javascript
手机注册发送验证码倒计时的简单实例
2017/11/15 Javascript
微信小程序实现同一页面取值的方法分析
2019/04/30 Javascript
Vue结合路由配置递归实现菜单栏功能
2020/06/16 Javascript
python中PIL安装简单教程
2016/04/21 Python
Python在线运行代码助手
2016/07/15 Python
python探索之BaseHTTPServer-实现Web服务器介绍
2017/10/28 Python
python3+PyQt5+Qt Designer实现堆叠窗口部件
2018/04/20 Python
python执行CMD指令,并获取返回的方法
2018/12/19 Python
Django REST Framework序列化外键获取外键的值方法
2019/07/26 Python
python+selenium 鼠标事件操作方法
2019/08/24 Python
Flask框架请求钩子与request请求对象用法实例分析
2019/11/07 Python
Python使用Matlab命令过程解析
2020/06/04 Python
捷克家具销售网站:SCONTO Nábytek
2020/01/02 全球购物
C/C++程序员常见面试题一
2012/12/08 面试题
小学开学寄语
2014/01/19 职场文书
教师中国梦演讲稿
2014/04/23 职场文书
教师自我剖析材料(群众路线)
2014/09/29 职场文书
2015年安全保卫工作总结
2015/05/14 职场文书
2015年小学语文教师工作总结
2015/10/23 职场文书
党务工作者主要事迹材料
2015/11/03 职场文书
《三国志》赏析
2019/08/27 职场文书
如何用python绘制雷达图
2021/04/24 Python
Golang 遍历二叉树
2022/04/19 Golang
详解Mysql事务并发(脏读、不可重复读、幻读)
2022/04/29 MySQL
python 学习GCN图卷积神经网络
2022/05/11 Python