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 27 Redis
基于Redis延迟队列的实现代码
May 13 Redis
详解Redis复制原理
Jun 04 Redis
Redis中一个String类型引发的惨案
Jul 25 Redis
springboot使用Redis作缓存使用入门教程
Jul 25 Redis
使用redis生成唯一编号及原理示例详解
Sep 15 Redis
关于SpringBoot 使用 Redis 分布式锁解决并发问题
Nov 17 Redis
Redis中缓存穿透/击穿/雪崩问题和解决方法
Dec 04 Redis
Redis 的查询很快的原因解析及Redis 如何保证查询的高效
Mar 16 Redis
Redis安装使用RedisJSON模块的方法
Mar 23 Redis
Grafana可视化监控系统结合SpringBoot使用
Apr 19 Redis
解决 redis 无法远程连接
May 15 Redis
Redis实战高并发之扣减库存项目
Redis中key的过期删除策略和内存淘汰机制
解决 Redis 秒杀超卖场景的高并发
redis 解决库存并发问题实现数量控制
Redis超详细讲解高可用主从复制基础与哨兵模式方案
redis复制有可能碰到的问题汇总
Apr 03 #Redis
 Redis 串行生成顺序编码的方法实现
You might like
PHP代码优化的53个细节
2014/03/03 PHP
PHP开发实现微信退款功能示例
2017/11/25 PHP
JavaScript 计算图片加载数量的代码
2011/01/01 Javascript
js定义对象或数组直接量时各浏览器对多余逗号的处理(json)
2011/03/05 Javascript
如何让easyui gridview 宽度自适应窗口改变及fitColumns应用
2013/01/25 Javascript
jQuery可见性过滤器:hidden和:visibility用法实例
2015/06/24 Javascript
js焦点文字滚动效果代码分享
2015/08/25 Javascript
JS提交form表单实例分析
2015/12/10 Javascript
BootStrap CSS全局样式和表格样式源码解析
2017/01/20 Javascript
angularjs+bootstrap菜单的使用示例代码
2017/03/07 Javascript
详解vue-router 2.0 常用基础知识点之router.push()
2017/05/10 Javascript
AngularJS实现动态添加Option的方法
2017/05/17 Javascript
webpack学习教程之publicPath路径问题详解
2017/06/17 Javascript
浅谈angular2 组件的生命周期钩子
2017/08/12 Javascript
微信web端后退强制刷新功能的实现代码
2018/03/04 Javascript
详解使用jest对vue项目进行单元测试
2018/09/07 Javascript
JavaScript的垃圾回收机制与内存管理
2020/08/06 Javascript
原生JS实现pc端轮播图效果
2020/12/21 Javascript
Python爬取成语接龙类网站
2018/10/19 Python
3分钟学会一个Python小技巧
2018/11/23 Python
pyqt5 comboBox获得下标、文本和事件选中函数的方法
2019/06/14 Python
Python监控服务器实用工具psutil使用解析
2019/12/19 Python
python动态文本进度条的实例代码
2020/01/22 Python
CSS3 实现的缩略图悬停效果
2020/12/09 HTML / CSS
基于html5绘制圆形多角图案
2016/04/21 HTML / CSS
html5需遵循的6个设计原则
2016/04/27 HTML / CSS
巴西食品补充剂在线零售商:Músculos na Web
2017/08/07 全球购物
Conforama瑞士:家具、厨房、电器、装饰
2020/09/06 全球购物
俄罗斯厨房产品购物网站:COOK HOUSE
2021/03/15 全球购物
护理专科自荐书范文
2014/02/18 职场文书
励志演讲稿800字
2014/08/21 职场文书
关于车尾的标语大全
2015/08/11 职场文书
教师节随笔
2015/08/15 职场文书
自愿离婚协议书范本2016
2016/03/18 职场文书
总结Python常用的魔法方法
2021/05/25 Python
总结Python变量的相关知识
2021/06/28 Python