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
redis通过6379端口无法连接服务器(redis-server.exe闪退)
May 08 Redis
为Java项目添加Redis缓存的方法
May 18 Redis
Django使用redis配置缓存的方法
Jun 01 Redis
Redis缓存-序列化对象存储乱码问题的解决
Jun 21 Redis
基于Redis结合SpringBoot的秒杀案例详解
Oct 05 Redis
Redis高并发防止秒杀超卖实战源码解决方案
Nov 01 Redis
Spring Boot实战解决高并发数据入库之 Redis 缓存+MySQL 批量入库问题
Feb 12 Redis
Redis之RedisTemplate配置方式(序列和反序列化)
Mar 13 Redis
Redis官方可视化工具RedisInsight安装使用教程
Apr 19 Redis
Redis数据同步之redis shake的实现方法
Apr 21 Redis
Redis实战高并发之扣减库存项目
Redis中key的过期删除策略和内存淘汰机制
解决 Redis 秒杀超卖场景的高并发
redis 解决库存并发问题实现数量控制
Redis超详细讲解高可用主从复制基础与哨兵模式方案
redis复制有可能碰到的问题汇总
Apr 03 #Redis
 Redis 串行生成顺序编码的方法实现
You might like
php格式化日期和时间格式化示例分享
2014/02/24 PHP
PHP往XML中添加节点的方法
2015/03/12 PHP
PHP JWT初识及其简单示例
2018/10/10 PHP
php+ajax 文件上传代码实例
2019/03/18 PHP
node.js中RPC(远程过程调用)的实现原理介绍
2014/12/05 Javascript
JavaScript插件化开发教程 (一)
2015/01/27 Javascript
JavaScript控制网页平滑滚动到指定元素位置的方法
2015/04/17 Javascript
jQuery切换所有复选框选中状态的方法
2015/07/02 Javascript
JS组件Form表单验证神器BootstrapValidator
2016/01/26 Javascript
vue动态组件实现选项卡切换效果
2017/03/08 Javascript
vue构建单页面应用实战
2017/04/10 Javascript
VUE 更好的 ajax 上传处理 axios.js实现代码
2017/05/10 Javascript
Vue下滚动到页面底部无限加载数据的示例代码
2018/04/22 Javascript
详解使用jest对vue项目进行单元测试
2018/09/07 Javascript
在Vue项目中引入JQuery-ui插件的讲解
2019/01/27 jQuery
详解vue更改头像功能实现
2019/04/28 Javascript
vue项目中在可编辑div光标位置插入内容的实现代码
2020/01/07 Javascript
vscode 配置vue+vetur+eslint+prettier自动格式化功能
2020/03/23 Javascript
解决vue中的无限循环问题
2020/07/27 Javascript
vant中的toast层级改变操作
2020/11/04 Javascript
Python获取服务器信息的最简单实现方法
2015/03/05 Python
Python的“二维”字典 (two-dimension dictionary)定义与实现方法
2016/04/27 Python
详解Django rest_framework实现RESTful API
2018/05/24 Python
使用Python爬取Json数据的示例代码
2020/12/07 Python
Spy++的使用方法及下载教程
2021/01/29 Python
Charles & Keith欧盟:新加坡时尚品牌
2019/08/01 全球购物
乌克兰珠宝大卖场:Zlato.ua
2020/09/27 全球购物
大学生求职简历的自我评价
2013/10/14 职场文书
酒吧总经理岗位职责
2013/12/10 职场文书
银行办公室岗位职责
2014/03/10 职场文书
留学经费担保书
2014/05/12 职场文书
教师师德师风整改措施
2014/10/24 职场文书
2015毕业生实习工作总结
2014/12/12 职场文书
毕业设计论文致谢词
2015/05/14 职场文书
导游词之开封禹王台风景区
2019/12/02 职场文书
selenium.webdriver中add_argument方法常用参数表
2021/04/08 Python