用Redis实现获取验证码,外加安全策略

安全策略

一小时内只能获取三次,一天内只能获取五次

Redis存储结构

在这里插入图片描述

代码展示

import cn.hutool.core.util.RandomUtil;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.StringRedisTemplate;

import javax.annotation.Resource;
import java.time.Duration;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.HashMap;
import java.util.Map;

@SpringBootTest
public class Test01 {
    @Resource
    private StringRedisTemplate stringRedisTemplate;

    private static final Logger logger = LogManager.getLogger(Test01.class);

    //redis前缀
    final String k = "YZM:COUNT:123456";
    //过期时间
    final Long EXPIRETIME = 1L;
    //一小时生成的次数
    final String HOURCOUNT = "hourCount";
    //24时生成的次数
    final String DAYCOUNT = "hourCount";
    //yzm
    final String YZM = "yzm";
    //校验一小时内的时间
    final String TIME = "time";

    //往Redis中存值
    public  void setYzm(DateTimeFormatter format,Integer hourCountStart,Integer dayCountStart,Boolean sign){
        logger.info("setYzm |start |往Redis中存值");

        //验证码的生成时间
        LocalDateTime now = LocalDateTime.now();
        //LocalDateTime转String
        String date = format.format(now);

        String yzm = RandomUtil.randomNumbers(6);
        //发送验证码
        logger.info("setYzm |····· |验证码:{}",yzm);

        //准备存储数据
        HashMap<String, String> yzmInfo = new HashMap<>();
        if (true==sign){
            yzmInfo.put("time",date);   //验证码生成时间
            logger.info("setYzm |····· |生成校验时间:{}",date);

        }
        yzmInfo.put("hourCount",hourCountStart.toString()); //一小时生成的次数
        yzmInfo.put("dayCount",dayCountStart.toString()); //24h生成的次数
        yzmInfo.put("yzm",yzm); //验证码

        //以hash的结果存入Redis中
        stringRedisTemplate.opsForHash().putAll(k,yzmInfo);
        Boolean expire = stringRedisTemplate.expire(k, Duration.ofDays(EXPIRETIME));
        logger.info("setYzm |end |Redis存储情况:{}",expire);

    }

    //获取校验时间,判断是否在一小时内
    public Boolean getTime(Map<Object, Object> redisMap,DateTimeFormatter format ){
        logger.info("getTime |start |取校验时间,判断是否在一小时内获取过验证码");
        String redisTime = redisMap.get(TIME).toString();
        //String转LocalDatetime
        LocalDateTime hourTime = LocalDateTime.parse(redisTime, format);
        //获取当前时间
        LocalDateTime now = LocalDateTime.now();
        //计算时间差,==0 代表一小时内的
        long betweenHours =  ChronoUnit.HOURS.between(hourTime , now );
        logger.info("getTime |···· |时间差:{}",betweenHours);
        if (betweenHours==0) {
            logger.info("getTime |end |结果是true");

            return true;
        }
        logger.info("getTime |end |结果是false");

        return false;
    }
    @Test
    public void getYzmPlus(){
        Integer hourCountStart = 1; //一小时生成的次数
        Integer dayCountStart = 1; //24h生成的次数
        //指定日期格式(格式化日期)
        DateTimeFormatter format = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

        //查看验证码次数
        Map<Object, Object> redisMap = stringRedisTemplate.opsForHash().entries(k);
        logger.info("验证码:{}",redisMap);

        Boolean sign = true;
        if (!redisMap.isEmpty()) {
            logger.info("验证码不为空,代表24h内不是第一次获取验证码");

            Integer hourCount = Integer.valueOf(redisMap.get(HOURCOUNT).toString());
            Integer dayCount = Integer.valueOf(redisMap.get(DAYCOUNT).toString());
            //判断是否一小时内发过验证码
            Boolean resut = getTime(redisMap, format);

            if (resut){
                if (hourCount==3){
                    logger.info("一小时内获取验证码次数上限了!");
                    throw new RuntimeException("一小时内获取验证码次数上限了!");
                }
                sign = false;
            }
            if (dayCount == 5){
                logger.info("24时内获取验证码次数上限了!");
                //返回
                throw new RuntimeException("24时内获取验证码次数上限了!");

            }

            //校验成功,发送验证码并set
            setYzm(format,hourCount+=1,dayCount+=1,sign);
        }else {
            logger.info("验证码为空,代表24h内第一次获取验证码");
            //发送验证码并set
            setYzm(format,hourCountStart,dayCountStart,sign);

        }
    }

}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/574859.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

正点原子[第二期]Linux之ARM(MX6U)裸机篇学习笔记-6

前言&#xff1a; 本文是根据哔哩哔哩网站上“正点原子[第二期]Linux之ARM&#xff08;MX6U&#xff09;裸机篇”视频的学习笔记&#xff0c;在这里会记录下正点原子 I.MX6ULL 开发板的配套视频教程所作的实验和学习笔记内容。本文大量引用了正点原子教学视频和链接中的内容。…

RK3588 - RKNN(Rockchip 神经处理单元)的逆向工程

本文翻译自https://jas-hacks.blogspot.com/2024/02/rk3588-reverse-engineering-rknn.html RK3588 NPU 的内部操作和功能主要隐藏在名为RKNPU2的闭源 SDK 中。由于对大型语言模型 (LLM) 的兴趣以及对transform模型最佳矩阵乘法的追求&#xff0c;想了解 RKNPU SDK 新引入的矩阵…

值得让英伟达CEO黄仁勋亲自给OpenAI配送的AI服务器!一文带你了解算力,GPU,CPU!

大家好&#xff0c;我是木易&#xff0c;一个持续关注AI领域的互联网技术产品经理&#xff0c;国内Top2本科&#xff0c;美国Top10 CS研究生&#xff0c;MBA。我坚信AI是普通人变强的“外挂”&#xff0c;所以创建了“AI信息Gap”这个公众号&#xff0c;专注于分享AI全维度知识…

【C++】双指针算法:和为s的两个数字

1.题目 虽然在牛客上是个中等题&#xff0c;但我感觉是比较简单的。大家在看完这篇文章后可以看看我的上一篇文章&#xff1a;有效三角形的个数。本文章的题目的解法只是有效三角形的个数这道题目的一个环节。看懂这篇文章后可以更好的解决有效三角形个数那道题目&#xff01; …

电力系统IEC-104报文主要常用详解

文章目录 1️⃣ IEC-1041.1 前言1.2 报文分类1.3 U帧报文1.3.1 常见报文1.3.1 报文解析 1.4 S帧报文1.4.1 说明1.4.2 报文解析 1.5 I帧报文1.5.1 报文解析 1.6 控制域I帧报文S帧报文U帧报文介绍 1.7 ASDU1.7.1 常见类型标识1.7.2 常见结构限定词1.7.3 常见传送原因1.7.4 信息体…

艾瑞泽5汽车电子控制单元CAN通信数据读写车辆网络系统交互接口

艾瑞泽5的网关接口数据交换通常涉及车辆内部电子设备之间的信息传输&#xff0c;包括车身系统、娱乐系统、远程控制、车辆状态监控、CAN数据采集分析、整车DBC控制策略等信息。 艾瑞泽5作为一款采用CAN协议的汽车&#xff0c;其CAN通信的开发可以提高车辆的安全性、可靠性和实…

Visual Studio Code使用

目录 1.python的调试 2.c的运行 方法1&#xff1a; 方法2&#xff1a; 3.c的调试 3.1调试方法一&#xff1a;先生成执行文件&#xff0c;再调试 3.2调试方法二&#xff1a;同时生成执行文件&#xff0c;调试 4.tasks.json 与launch.json文件的参考 4.1C生成执行文件tas…

uniapp H5实现签名

第一种&#xff1a;跳转签名页面 1、创建审核页面audit.vue <template><view><uni-section title""><view class"auditClass"><uni-forms :model"baseFormData" ref"baseFormRef" :rules"rules&quo…

数据结构初阶——树和二叉树

数据结构初阶——树和二叉树 1. 树的概念和结构1.1 树的概念1.2 树的表示 2. 二叉树2.1 二叉树的概念和结构2.2 二叉树的存储结构2.2.1 顺序存储2.2.2 链式存储 3. 二叉树的顺序结构及实现——堆3.1 堆的概念和结构3.2 堆的实现3.2.1 堆的定义3.2.2 堆的向上调整3.2.3 堆的向下…

【网络安全】安全事件管理处置 — 事件分级分类

专栏文章索引&#xff1a;网络安全 有问题可私聊&#xff1a;QQ&#xff1a;3375119339 目录 一、安全事件分级 二、应急事件分级 三、安全事件分类 四、常见安全事件原因分析 1.web入侵 2.漏洞攻击 3.网络攻击 一、安全事件分级 在对安全事件的应急响应过程中&#xf…

【Hadoop】-Apache Hive概述 Hive架构[11]

目录 Apache Hive概述 一、分布式SQL计算-Hive 二、为什么使用Hive Hive架构 一、Hive组件 Apache Hive概述 Apache Hive是一个在Hadoop上构建的数据仓库基础设施&#xff0c;它提供了一个SQL-Like查询语言来分析和查询大规模的数据集。Hive将结构化查询语言&#xff08;…

LT8711UXD助力新款Swtich游戏机底座《4K/60HZ投屏方案》

Nintendo Switch&#xff08;OLED版&#xff09;正面搭载了一块分辨率为720P的7.0英寸OLED屏幕&#xff1b;具有白色和电光蓝电光红2种颜色&#xff1b;机身长度102毫米&#xff0c;宽度242毫米&#xff0c;厚度13.9毫米&#xff0c;重量约420克。 [2]Nintendo Switch&#xff…

明天报名!!济宁教师招聘报名照片及常见问题

明天报名!!济宁教师招聘报名照片及常见问题 山东济宁教师招聘1000多人 报名时间: 2024年4月25日9:00-4月28日16:00 缴费时间: 2024年4月25日11:00-4月30日16:00 打印准考证:2024年5月23日9:00-5月26日9:30 初审时间: 2024年4月25日11:00-4月29日16:00 查询时间: 2024年4月…

10、了解JVM判断对象可回收的神秘法则!

10.1、垃圾回收触发时机? 在我们之前的学习中,我们已经了解到,当我们的系统在运行过程中创建对象时,这些对象通常会被优先分配在所谓的“新生代”内存区域,如下图所示。 在新生代中,当对象数量逐渐增多,接近填满整个空间时,会触发垃圾回收机制。这个机制的作用是回收…

人工智能(pytorch)搭建模型28-基于Transformer的端到端目标检测DETR模型的实际应用,DETR的原理与结构

大家好&#xff0c;我是微学AI&#xff0c;今天给大家介绍一下人工智能(pytorch)搭建模型28-基于Transformer的端到端目标检测DETR模型的实际应用&#xff0c;DETR的原理与结构。DETR&#xff08;Detected Transformers&#xff09;是一种基于Transformer的端到端目标检测模型&…

IPV4报文格式和IP分片及计算

目录 1.IPV4报文格式 2.IP分片及计算 1.IPV4报文格式 版本&#xff1a;四位&#xff0c;IPV4 0100 4 ;IPV6 0110 6头部长度(IHL):最小值是5&#xff0c;最大值为15&#xff0c;单位4字节。IPV6固定头部长度40字节TOS:为区分服务字段&#xff0c;用区分服务类型&#xff0c;即…

半导体晶圆厂内外网数据单向导出,什么样的方案才安全又便捷?

半导体晶圆厂企业为了隔绝外部⽹络有害攻击、保护⽹络和数据安全&#xff0c;通常采⽤物理隔离的⽅式&#xff0c;将企业内⽹与互联⽹隔离。⽹络隔离后&#xff0c;基于业务开展需求&#xff0c;部分重要数据仍需由内⽹导⼊及导出⾄外部⽹络区域。为保障数据的安全合规性&#…

VMware配置centos虚拟机实现内网互通

VMware配置centos虚拟机实现内网互通 一、安装无桌面模式 环境说明&#xff1a; VMWare版本&#xff1a;VMware Workstation 17 Pro Centos版本&#xff1a;CentOS-7.9-x86_64-DVD-2009.iso 一键下载本文资源包 1. 安装虚拟机 下面是创建具体步骤,其中需要注意的是&#xff1…

如何优雅的实现 iframe 多层级嵌套通讯

前言 在前端开发项目中&#xff0c;不可避免的总会和 iframe 进行打交道&#xff0c;我们通常会使用 postMessage 实现消息通讯。 如果存在下面情况&#xff1a; iframe 父子通讯iframe 同层级通讯iframe 嵌套层级通讯 当面对这种复杂的情况的时候&#xff0c;通讯不可避免…

uniapp制作安卓原生插件踩坑

1.uniapp和Android工程互相引用讲解 uniapp原生Android插件开发入门教程 &#xff08;最新版&#xff09;_uniapp android 插件开发-CSDN博客 2.uniapp引用原生aar目录结构 详细尝试步骤1完成后生成的aar使用&#xff0c;需要新建nativeplugins然后丢进去 3.package.json示例…