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 15 Redis
SpringBoot 集成Redis 过程
Jun 02 Redis
解析Redis Cluster原理
Jun 21 Redis
Redis主从配置和底层实现原理解析(实战记录)
Jun 30 Redis
使用Redis实现实时排行榜功能
Jul 02 Redis
Redis性能监控的实现
Jul 09 Redis
Redis的字符串是如何实现的
Oct 24 Redis
redis中lua脚本使用教程
Nov 01 Redis
聊聊redis-dump工具安装问题
Jan 18 Redis
Redis sentinel哨兵集群的实现步骤
Jul 15 Redis
redis lua限流算法实现示例
Jul 15 Redis
Redis实战高并发之扣减库存项目
Redis中key的过期删除策略和内存淘汰机制
解决 Redis 秒杀超卖场景的高并发
redis 解决库存并发问题实现数量控制
Redis超详细讲解高可用主从复制基础与哨兵模式方案
redis复制有可能碰到的问题汇总
Apr 03 #Redis
 Redis 串行生成顺序编码的方法实现
You might like
PHP中HTTP方式下的Gzip压缩传输方法举偶
2007/02/15 PHP
Smarty+QUICKFORM小小演示
2007/02/25 PHP
php smarty模板引擎的6个小技巧
2014/04/24 PHP
php中实现xml与mysql数据相互转换的方法
2014/12/25 PHP
ThinkPHP3.2.3实现分页的方法详解
2016/06/03 PHP
热点新闻滚动特效的js代码
2013/08/17 Javascript
js判断iframe内的网页是否滚动到底部触发事件
2014/03/18 Javascript
Javascript基础教程之switch语句
2015/01/18 Javascript
php利用curl获取远程图片实现方法
2015/10/26 Javascript
JS获取和修改元素样式的实例代码
2016/08/06 Javascript
微信小程序 navigation API实例详解
2016/10/02 Javascript
微信小程序 时间格式化(util.formatTime(new Date))详解
2016/11/16 Javascript
javascript中BOM基础知识总结
2017/02/14 Javascript
Web开发中客户端的跳转与服务器端的跳转的区别
2017/03/05 Javascript
iview给radio按钮组件加点击事件的实例
2017/09/30 Javascript
Express的HTTP重定向到HTTPS的方法
2018/06/06 Javascript
JavaScript读写二进制数据的方法详解
2018/09/09 Javascript
JavaScript设计模式之观察者模式实例详解
2019/01/16 Javascript
JavaScript 扩展运算符用法实例小结【基于ES6】
2019/06/17 Javascript
JavaScript Date对象功能与用法学习记录
2020/04/28 Javascript
在Python中使用pngquant压缩png图片的教程
2015/04/09 Python
Python创建xml文件示例
2017/03/22 Python
python实现逻辑回归的方法示例
2017/05/02 Python
Python使用MD5加密算法对字符串进行加密操作示例
2018/03/30 Python
使用Python将字符串转换为格式化的日期时间字符串
2019/09/01 Python
使用pytorch搭建AlexNet操作(微调预训练模型及手动搭建)
2020/01/18 Python
如何使用Python自动生成报表并以邮件发送
2020/10/15 Python
ellesse美国官方商店:意大利高级运动服品牌
2019/10/29 全球购物
计算机专业推荐信范文
2013/11/27 职场文书
2014年情人节活动方案
2014/02/16 职场文书
道德大讲堂实施方案
2014/05/14 职场文书
天猫活动策划方案
2014/08/21 职场文书
行政复议答复书
2015/07/01 职场文书
优质服务标语口号
2015/12/26 职场文书
Mysql中有关Datetime和Timestamp的使用总结
2021/12/06 MySQL
Linux中各个目录的作用与内容
2022/06/28 Servers