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 sentinel 频繁主备切换的问题
Apr 12 Redis
基于Redis过期事件实现订单超时取消
May 08 Redis
Redis 彻底禁用RDB持久化操作
Jul 09 Redis
Redis源码阅读:Redis字符串SDS详解
Jul 15 Redis
嵌入式Redis服务器在Spring Boot测试中的使用教程
Jul 21 Redis
Redis入门教程详解
Aug 30 Redis
基于Redis的List实现特价商品列表功能
Aug 30 Redis
浅谈Redis跟MySQL的双写问题解决方案
Feb 24 Redis
在Centos 8.0中安装Redis服务器的教程详解
Mar 21 Redis
redis调用二维码时的不断刷新排查分析
Apr 01 Redis
Redis批量生成数据的实现
Jun 05 Redis
Redis实战高并发之扣减库存项目
Redis中key的过期删除策略和内存淘汰机制
解决 Redis 秒杀超卖场景的高并发
redis 解决库存并发问题实现数量控制
Redis超详细讲解高可用主从复制基础与哨兵模式方案
redis复制有可能碰到的问题汇总
Apr 03 #Redis
 Redis 串行生成顺序编码的方法实现
You might like
require(),include(),require_once()和include_once()区别
2008/03/27 PHP
php UTF-8、Unicode和BOM问题
2010/05/18 PHP
PHP Trait代码复用类与多继承实现方法详解
2019/06/17 PHP
jQuery插件jFade实现鼠标经过的图片高亮其它变暗
2015/03/14 Javascript
js+div实现文字滚动和图片切换效果代码
2015/08/27 Javascript
js滚轮事件兼容性问题需要注意哪些
2016/11/15 Javascript
JS实现上传图片实时预览功能
2017/05/22 Javascript
Bootstrap按钮组实例详解
2017/07/03 Javascript
Vue实例中生命周期created和mounted的区别详解
2017/08/25 Javascript
VUE2.0+Element-UI+Echarts封装的组件实例
2018/03/02 Javascript
nodejs基于express实现文件上传的方法
2018/03/19 NodeJs
JavaScript求一组数的最小公倍数和最大公约数常用算法详解【面向对象,回归迭代和循环】
2018/05/07 Javascript
关于layui 弹出层一闪而过就消失的解决方法
2019/09/09 Javascript
vue或react项目生产环境去掉console.log的操作
2020/09/02 Javascript
Vue proxyTable配置多个接口地址,解决跨域的问题
2020/09/11 Javascript
[03:32]2014DOTA2西雅图邀请赛 CIS外卡赛赛前black专访
2014/07/09 DOTA
Python代码调试的几种方法总结
2015/04/15 Python
python 禁止函数修改列表的实现方法
2017/08/03 Python
详解Python的hasattr() getattr() setattr() 函数使用方法
2018/07/09 Python
Python+OpenCV采集本地摄像头的视频
2019/04/25 Python
Python登录系统界面实现详解
2019/06/25 Python
Django使用模板后无法找到静态资源文件问题解决
2019/07/19 Python
Django REST框架创建一个简单的Api实例讲解
2019/11/05 Python
wxpython多线程防假死与线程间传递消息实例详解
2019/12/13 Python
python使用多线程+socket实现端口扫描
2020/05/28 Python
python实现图片,视频人脸识别(dlib版)
2020/11/18 Python
ziaja齐叶雅官方海外旗舰店:来自波兰的天然护肤品牌
2017/01/02 全球购物
美国医疗用品、医疗设备和家庭保健用品商店:Medical Supply Depot
2018/07/08 全球购物
Feelunique美国:欧洲大型的在线美妆零售电商
2018/11/04 全球购物
拉飞逸官网:Lafayette 148 New York
2020/07/15 全球购物
电子商务网站的创业计划书
2014/01/05 职场文书
追悼会子女答谢词
2014/01/28 职场文书
税务干部群众路线教育实践活动自我剖析材料
2014/09/21 职场文书
个人先进材料范文
2014/12/30 职场文书
pytorch 一行代码查看网络参数总量的实现
2021/05/12 Python
V Rising 服务器搭建图文教程
2022/06/16 Servers