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 13 Redis
redis内存空间效率问题的深入探究
May 17 Redis
redis requires ruby version2.2.2的解决方案
Jul 15 Redis
springboot使用Redis作缓存使用入门教程
Jul 25 Redis
Springboot/Springcloud项目集成redis进行存取的过程解析
Dec 04 Redis
Redis 中使用 list,streams,pub/sub 几种方式实现消息队列的问题
Mar 16 Redis
Redis如何实现验证码发送 以及限制每日发送次数
Apr 18 Redis
Redis实现订单过期删除的方法步骤
Jun 05 Redis
浅谈Redis变慢的原因及排查方法
Jun 21 Redis
Redis+AOP+自定义注解实现限流
Jun 28 Redis
Redis实战高并发之扣减库存项目
Redis中key的过期删除策略和内存淘汰机制
解决 Redis 秒杀超卖场景的高并发
redis 解决库存并发问题实现数量控制
Redis超详细讲解高可用主从复制基础与哨兵模式方案
redis复制有可能碰到的问题汇总
Apr 03 #Redis
 Redis 串行生成顺序编码的方法实现
You might like
PHP在XP下IIS和Apache2服务器上的安装
2006/09/05 PHP
PHP 错误之引号中使用变量
2009/05/04 PHP
Code:findPosX 和 findPosY
2006/12/20 Javascript
Javascript操作select方法大全[新增、修改、删除、选中、清空、判断存在等]
2008/09/26 Javascript
jQuery弹出层始终垂直居中相对于屏幕或当前窗口
2013/04/01 Javascript
jquery bind(click)传参让列表中每行绑定一个事件
2014/08/06 Javascript
JavaScript判断文件上传类型的方法
2014/09/02 Javascript
检测一个函数是否是JavaScript原生函数的小技巧
2015/03/13 Javascript
jQuery 3.0 的变化及使用方法
2016/02/01 Javascript
uniapp微信小程序:key失效的解决方法
2021/01/20 Javascript
[01:25]DOTA2超级联赛专访iG 将调整状态找回自己
2013/06/05 DOTA
[05:00]TI9战队采访 - Royal Never Give Up
2019/08/20 DOTA
Python设计实现的计算器功能完整实例
2017/08/18 Python
基于python 字符编码的理解
2017/09/02 Python
python利用urllib和urllib2访问http的GET/POST详解
2017/09/27 Python
用tensorflow搭建CNN的方法
2018/03/05 Python
python使用PIL模块获取图片像素点的方法
2019/01/08 Python
Python GUI编程完整示例
2019/04/04 Python
详解python列表(list)的使用技巧及高级操作
2019/08/15 Python
django创建简单的页面响应实例教程
2019/09/06 Python
利用python计算时间差(返回天数)
2019/09/07 Python
django框架创建应用操作示例
2019/09/26 Python
PYQT5开启多个线程和窗口,多线程与多窗口的交互实例
2019/12/13 Python
Python常用库大全及简要说明
2020/01/17 Python
css3media响应式布局实例
2016/07/08 HTML / CSS
什么是类的返射机制
2016/02/06 面试题
什么是Web Service?
2012/07/25 面试题
大专生工程监理求职信
2013/10/04 职场文书
平面设计岗位职责
2013/12/14 职场文书
制药工程专业毕业生推荐信
2013/12/24 职场文书
应届护士求职信范文
2014/01/26 职场文书
食堂采购员岗位职责
2014/03/17 职场文书
2014年中秋寄语
2014/08/11 职场文书
整改落实情况汇报材料
2014/10/29 职场文书
Python selenium模拟网页点击爬虫交管12123违章数据
2021/05/26 Python
PostgreSQL之连接失败的问题及解决
2023/05/08 PostgreSQL