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
详解RedisTemplate下Redis分布式锁引发的系列问题
Apr 27 Redis
Windows中Redis安装配置流程并实现远程访问功能
Jun 07 Redis
k8s部署redis cluster集群的实现
Jun 24 Redis
使用Redis实现实时排行榜功能
Jul 02 Redis
springboot使用Redis作缓存使用入门教程
Jul 25 Redis
使用redis生成唯一编号及原理示例详解
Sep 15 Redis
Redis高可用集群redis-cluster详解
Mar 20 Redis
windows安装 redis 6.2.6最新步骤详解
Apr 26 Redis
Redis基本数据类型Set常用操作命令
Jun 01 Redis
浅谈Redis缓冲区机制
Jun 05 Redis
python中使用redis用法详解
Dec 24 Redis
Redis实战高并发之扣减库存项目
Redis中key的过期删除策略和内存淘汰机制
解决 Redis 秒杀超卖场景的高并发
redis 解决库存并发问题实现数量控制
Redis超详细讲解高可用主从复制基础与哨兵模式方案
redis复制有可能碰到的问题汇总
Apr 03 #Redis
 Redis 串行生成顺序编码的方法实现
You might like
PHP按行读取文件时删除换行符的3种方法
2014/05/04 PHP
PHP实现获取某个月份周次信息的方法
2015/08/11 PHP
javascript call和apply方法
2008/11/24 Javascript
jquery 日期分离成年月日的代码
2010/05/14 Javascript
javascript预览上传图片发现的问题的解决方法
2010/11/25 Javascript
javascript中万恶的function实例分析
2011/05/25 Javascript
Prototype源码浅析 Number部分
2012/01/16 Javascript
jquery 实现表单验证功能代码(简洁)
2012/07/03 Javascript
使用jQuery判断Div是否在可视区域的方法 判断div是否可见
2016/02/17 Javascript
微信小程序本作用域下调用全局JS详解及实例
2017/02/22 Javascript
Angular.JS去掉访问路径URL中的#号详解
2017/03/30 Javascript
BootStrap 导航条实例代码
2017/05/18 Javascript
如何在Angular应用中创建包含组件方法示例
2019/03/23 Javascript
小程序两种滚动公告栏的实现方法
2019/09/17 Javascript
Websocket 向指定用户发消息的方法
2020/01/09 Javascript
微信小程序自定义yPicker组件实现省市区三级联动功能
2020/10/29 Javascript
[53:38]OG vs LGD 2018国际邀请赛淘汰赛BO3 第三场 8.26
2018/08/30 DOTA
Python操作MongoDB数据库PyMongo库使用方法
2015/04/27 Python
python将字符串转换成数组的方法
2015/04/29 Python
python结合shell查询google关键词排名的实现代码
2016/02/27 Python
django 删除数据库表后重新同步的方法
2018/05/27 Python
python操作redis方法总结
2018/06/06 Python
Django跨域请求CSRF的方法示例
2018/11/11 Python
python安装scipy的方法步骤
2019/06/26 Python
微软英国官方网站:Microsoft英国
2016/10/15 全球购物
台湾线上百货零售购物平台:friDay购物
2017/08/18 全球购物
日本订房网站,预订日本星级酒店/温泉旅馆:Relux(支持中文)
2020/01/03 全球购物
程序集与命名空间有什么不同
2014/07/25 面试题
Linux操作面试题
2015/02/11 面试题
Ruby如何定义一个类
2012/10/08 面试题
教育孩子心得体会
2014/01/01 职场文书
实习单位接收函
2014/01/11 职场文书
党校培训自我鉴定范文
2014/03/20 职场文书
Python 中 Shutil 模块详情
2021/11/11 Python
Java基于Dijkstra算法实现校园导游程序
2022/03/17 Java/Android
MySQL常用慢查询分析工具详解
2022/08/14 MySQL