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数据结构之链表与字典的使用
May 11 Redis
浅谈Redis主从复制以及主从复制原理
May 29 Redis
Windows中Redis安装配置流程并实现远程访问功能
Jun 07 Redis
Redis做数据持久化的解决方案及底层原理
Jul 15 Redis
浅谈Redis位图(Bitmap)及Redis二进制中的问题
Jul 15 Redis
Redis中一个String类型引发的惨案
Jul 25 Redis
使用redis实现延迟通知功能(Redis过期键通知)
Sep 04 Redis
CentOS8.4安装Redis6.2.6的详细过程
Nov 20 Redis
Spring Boot实战解决高并发数据入库之 Redis 缓存+MySQL 批量入库问题
Feb 12 Redis
解决Redis启动警告问题
Feb 24 Redis
muduo TcpServer模块源码分析
Apr 26 Redis
Redis入门基础常用操作命令整理
Jun 01 Redis
Redis实战高并发之扣减库存项目
Redis中key的过期删除策略和内存淘汰机制
解决 Redis 秒杀超卖场景的高并发
redis 解决库存并发问题实现数量控制
Redis超详细讲解高可用主从复制基础与哨兵模式方案
redis复制有可能碰到的问题汇总
Apr 03 #Redis
 Redis 串行生成顺序编码的方法实现
You might like
深入php self与$this的详解
2013/06/08 PHP
php后门URL的防范
2013/11/12 PHP
php使用ereg验证文件上传的方法
2014/12/16 PHP
简单谈谈php浮点数精确运算
2016/03/10 PHP
用jquery等比例控制图片宽高的具体实现
2014/01/28 Javascript
浅谈jQuery中height与width
2015/07/06 Javascript
Js 获取当前函数参数对象的实现代码
2016/06/20 Javascript
AngularJS 表达式详细讲解及实例代码
2016/07/26 Javascript
js 原生判断内容区域是否滚动到底部的实例代码
2017/11/15 Javascript
vue的mixins属性详解
2018/03/14 Javascript
Koa代理Http请求的示例代码
2018/10/10 Javascript
vue实现自定义H5视频播放器的方法步骤
2019/07/01 Javascript
Echarts地图添加引导线效果(labelLine)
2019/09/30 Javascript
微信小程序定义和调用全局变量globalData的实现
2019/11/01 Javascript
JavaScript实现前端倒计时效果
2021/02/09 Javascript
web.py中调用文件夹内模板的方法
2014/08/26 Python
用Python创建声明性迷你语言的教程
2015/04/13 Python
python selenium UI自动化解决验证码的4种方法
2018/01/05 Python
python实现括号匹配的思路详解
2018/08/23 Python
Python使用while循环花式打印乘法表
2019/01/28 Python
python滑块验证码的破解实现
2019/11/10 Python
Python二维数组实现求出3*3矩阵对角线元素的和示例
2019/11/29 Python
pytorch实现onehot编码转为普通label标签
2020/01/02 Python
详解pycharm的python包opencv(cv2)无代码提示问题的解决
2021/01/29 Python
使用CSS3代码绘制可爱的Hello Kitty猫
2016/08/03 HTML / CSS
CSS3实现滚动条动画效果代码分享
2016/08/03 HTML / CSS
基于CSS3的animation属性实现微信拍一拍动画效果
2020/06/22 HTML / CSS
Javascript如何发送一个Ajax请求
2015/01/26 面试题
总经理助理岗位职责
2013/11/08 职场文书
教师专业理论水平的自我评价分享
2013/11/09 职场文书
会计岗位职责模板
2014/03/12 职场文书
五一活动标语
2014/06/30 职场文书
2016拓展训练心得体会范文
2016/01/12 职场文书
MySQL查询学习之基础查询操作
2021/05/08 MySQL
多线程Spring通过@Scheduled实现定时任务
2022/05/25 Java/Android
JS前端使用Canvas快速实现手势解锁特效
2022/09/23 Javascript