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 08 Redis
分布式锁为什么要选择Zookeeper而不是Redis?看完这篇你就明白了
May 21 Redis
redis实现排行榜功能
May 24 Redis
详解Redis复制原理
Jun 04 Redis
聊一聊Redis与MySQL双写一致性如何保证
Jun 26 Redis
缓存替换策略及应用(以Redis、InnoDB为例)
Jul 25 Redis
解决linux下redis数据库overcommit_memory问题
Feb 24 Redis
Redis实战高并发之扣减库存项目
Apr 14 Redis
Redis 限流器
May 15 Redis
Redis基本数据类型Zset有序集合常用操作
Jun 01 Redis
Redis实现订单过期删除的方法步骤
Jun 05 Redis
基于redis+lua进行限流的方法
Jul 23 Redis
Redis实战高并发之扣减库存项目
Redis中key的过期删除策略和内存淘汰机制
解决 Redis 秒杀超卖场景的高并发
redis 解决库存并发问题实现数量控制
Redis超详细讲解高可用主从复制基础与哨兵模式方案
redis复制有可能碰到的问题汇总
Apr 03 #Redis
 Redis 串行生成顺序编码的方法实现
You might like
一个很方便的 XML 类!!原创的噢
2006/10/09 PHP
PHP版国家代码、缩写查询函数代码
2011/08/14 PHP
Drupal7 form表单二次开发要点与实例
2014/03/02 PHP
php验证码生成器
2017/05/24 PHP
PHP实现的观察者模式实例
2017/06/21 PHP
php中青蛙跳台阶的问题解决方法
2018/10/14 PHP
js变量作用域及可访问性的探讨
2006/11/23 Javascript
JQuery 风格的HTML文本转义
2009/07/01 Javascript
JavaScript flash复制库类 Zero Clipboard
2011/01/17 Javascript
javascript关于运动的各种问题经典总结
2015/04/27 Javascript
nodejs简单实现中英文翻译
2015/05/04 NodeJs
基于jQuery通过jQuery.form.js插件使用ajax提交form表单
2015/08/17 Javascript
微信小程序 JS动态修改样式的实现代码
2017/02/10 Javascript
mui上拉加载功能实例详解
2017/04/13 Javascript
浅谈js基础数据类型和引用类型,深浅拷贝问题,以及内存分配问题
2017/09/02 Javascript
JS实现简单的浮动碰撞效果示例
2017/12/28 Javascript
vue3.0 CLI - 2.5 - 了解组件的三维
2018/09/14 Javascript
详解vue-cli 2.0配置文件(小结)
2019/01/14 Javascript
新手快速入门微信小程序组件库 iView Weapp
2019/06/24 Javascript
Angular 多级路由实现登录页面跳转(小白教程)
2019/11/19 Javascript
bootstrap-paginator服务器端分页使用方法详解
2020/02/13 Javascript
javascript设计模式 ? 解释器模式原理与用法实例分析
2020/04/17 Javascript
Python单例模式实例分析
2015/01/14 Python
python实现基于SVM手写数字识别功能
2020/05/27 Python
flask中主动抛出异常及统一异常处理代码示例
2018/01/18 Python
python读取Excel实例详解
2018/08/17 Python
详解python-图像处理(映射变换)
2019/03/22 Python
python+Selenium自动化测试——输入,点击操作
2020/03/06 Python
浅谈Keras的Sequential与PyTorch的Sequential的区别
2020/06/17 Python
python如何绘制疫情图
2020/09/16 Python
浅析canvas元素的html尺寸和css尺寸对元素视觉的影响
2019/07/22 HTML / CSS
Html5饼图绘制实现统计图的方法
2020/08/05 HTML / CSS
Expedia英国:全球最大的在线旅游公司
2017/09/07 全球购物
什么是ESB?请介绍一下ESB?
2015/05/27 面试题
市场营销专科应届生求职信
2013/11/24 职场文书
Docker官方工具docker-registry案例演示
2022/04/13 Servers