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
基于Redis位图实现用户签到功能
May 08 Redis
浅谈Redis的几个过期策略
May 27 Redis
压缩Redis里的字符串大对象操作
Jun 23 Redis
Redis 彻底禁用RDB持久化操作
Jul 09 Redis
在项目中使用redis做缓存的一些思路
Sep 14 Redis
redis缓存存储Session原理机制
Nov 20 Redis
Springboot/Springcloud项目集成redis进行存取的过程解析
Dec 04 Redis
浅谈Redis跟MySQL的双写问题解决方案
Feb 24 Redis
Redis 中使用 list,streams,pub/sub 几种方式实现消息队列的问题
Mar 16 Redis
使用Redis实现点赞取消点赞的详细代码
Mar 20 Redis
python中使用redis用法详解
Dec 24 Redis
Redis实战高并发之扣减库存项目
Redis中key的过期删除策略和内存淘汰机制
解决 Redis 秒杀超卖场景的高并发
redis 解决库存并发问题实现数量控制
Redis超详细讲解高可用主从复制基础与哨兵模式方案
redis复制有可能碰到的问题汇总
Apr 03 #Redis
 Redis 串行生成顺序编码的方法实现
You might like
用php写的serv-u的web申请账号的程序
2006/10/09 PHP
一些使用频率比较高的php函数
2008/10/03 PHP
php如何解决无法上传大于8M的文件问题
2014/03/10 PHP
php判断电脑访问、手机访问的例子
2014/05/10 PHP
浅谈ThinkPHP的URL重写
2014/11/25 PHP
php查找字符串出现次数的方法
2014/12/01 PHP
PHP导入导出Excel代码
2015/07/07 PHP
JavaScript 在各个浏览器中执行的耐性
2009/04/06 Javascript
基于jquery实现漂亮的动态信息提示效果
2011/08/02 Javascript
jquery中使用$(#form).submit()重写提交表单无效原因分析及解决
2013/03/25 Javascript
js操作label给label赋值及取label的值示例
2013/11/07 Javascript
jQuery 判断图片是否加载完成方法汇总
2015/08/10 Javascript
基于JS代码实现实时显示系统时间
2016/06/16 Javascript
jquery html5 视频播放控制代码
2016/11/06 Javascript
jQuery自定义元素右键点击事件(实现案例)
2017/04/28 jQuery
jQuery实现checkbox的简单操作
2017/11/18 jQuery
[03:11]TI9战队档案 - Alliance
2019/08/20 DOTA
Python探索之爬取电商售卖信息代码示例
2017/10/27 Python
Python批量发送post请求的实现代码
2018/05/05 Python
django缓存配置的几种方法详解
2018/07/16 Python
python使用mitmproxy抓取浏览器请求的方法
2019/07/02 Python
Django项目使用CircleCI的方法示例
2019/07/14 Python
使用Python快乐学数学Github万星神器Manim简介
2019/08/07 Python
Python中的wordcloud库安装问题及解决方法
2020/05/27 Python
Python之qq自动发消息的示例代码
2021/02/18 Python
国际旅客访问北美最大的汽车租赁提供商:Alamo Rent A Car
2018/06/13 全球购物
无工作经验者个人求职信范文
2013/12/22 职场文书
校园创业策划书
2014/01/14 职场文书
大学生职业生涯规划书汇总
2014/03/20 职场文书
党性锻炼的心得体会
2014/09/03 职场文书
教师四风对照检查材料思想汇报
2014/09/17 职场文书
导游词之日本富士山
2020/01/06 职场文书
nginx proxy_cache 缓存配置详解
2021/03/31 Servers
Python实现简单的俄罗斯方块游戏
2021/09/25 Python
MySQL时区造成时差问题
2022/04/13 MySQL
springboot实现string转json json里面带数组
2022/06/16 Java/Android