当前位置: 首页 > news >正文

使用Redis记录错误次数、序列号锁定和冻结时间的实现步骤示例[超详细]

使用Redis记录错误次数、序列号锁定和冻结时间的实现步骤

在本文中,我们将详细介绍如何使用Redis来记录错误次数、序列号锁定和冻结时间。通过Spring Boot和Spring Data Redis,我们能够轻松实现这些功能。

依赖

首先,确保你的项目中包含以下依赖:

  1. Spring Boot
  2. Spring Data Redis

pom.xml 中添加以下依赖:

<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency><!-- 其他依赖 -->
</dependencies>

配置

application.yml 中配置Redis连接:

spring:redis:host: localhostport: 6379

实现

接下来,编写服务类和控制器来实现需求。

Redis配置类

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;@Configuration
public class RedisConfig {@Beanpublic RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {RedisTemplate<String, Object> template = new RedisTemplate<>();template.setConnectionFactory(factory);template.setKeySerializer(new StringRedisSerializer());template.setValueSerializer(new StringRedisSerializer());return template;}
}

服务类

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import java.util.concurrent.TimeUnit;@Service
public class ValidationService {private static final String NAME_ID_KEY = "name_id:";private static final String CARD_ERROR_KEY = "card_error:";private static final int LOCK_TIME = 5; // minutesprivate static final int MAX_ATTEMPTS = 5;@Autowiredprivate RedisTemplate<String, Object> redisTemplate;public boolean validateNameAndId(String name, String id, String correctName, String correctId) {if (name.equals(correctName) && id.equals(correctId)) {return true;}if (!name.equals(correctName)) {throw new IllegalArgumentException("姓名输入错误,请重新输入");}if (!id.equals(correctId)) {throw new IllegalArgumentException("工号输入错误,请重新输入");}return false;}public void validateCard(String serialNumber, String inputCard, String correctCard) {String cardErrorKey = CARD_ERROR_KEY + serialNumber;// 检查是否已锁定if (Boolean.TRUE.equals(redisTemplate.hasKey(cardErrorKey)) && redisTemplate.getExpire(cardErrorKey) > 0) {throw new IllegalStateException("密码错误次数过多,请稍后再试");}// 获取当前错误次数int attempts = redisTemplate.opsForValue().get(cardErrorKey) == null ? 0 : (int) redisTemplate.opsForValue().get(cardErrorKey);if (!inputCard.equals(correctCard)) {attempts++;if (attempts >= MAX_ATTEMPTS) {// 超过最大尝试次数,锁定序列号redisTemplate.opsForValue().set(cardErrorKey, attempts, LOCK_TIME, TimeUnit.MINUTES);throw new IllegalStateException("密码错误次数过多,请稍后再试");} else {// 更新错误次数redisTemplate.opsForValue().set(cardErrorKey, attempts);throw new IllegalArgumentException(String.format("卡密已输入错误%d次,超过%d次将锁定", attempts, MAX_ATTEMPTS));}} else {// ��证成功,清除错误次数redisTemplate.delete(cardErrorKey);}}
}

控制器

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;@RestController
@RequestMapping("/api/validate")
public class ValidationController {@Autowiredprivate ValidationService validationService;@PostMapping("/name-id")public String validateNameAndId(@RequestParam String name, @RequestParam String id) {// 假设 correctName 和 correctId 是从数据库或其他地方获取的正确值String correctName = "正确的姓名";String correctId = "正确的工号";try {validationService.validateNameAndId(name, id, correctName, correctId);return "姓名和工号校验通过";} catch (IllegalArgumentException e) {return e.getMessage();}}### 控制器```java@PostMapping("/card")public String validateCard(@RequestParam String serialNumber, @RequestParam String inputCard) {// 假设 correctCard 是从数据库或其他地方获取的正确卡密String correctCard = "正确的卡密";try {validationService.validateCard(serialNumber, inputCard, correctCard);return "卡密校验通过";} catch (IllegalArgumentException e) {return e.getMessage();} catch (IllegalStateException e) {return e.getMessage();}}
}

详细解析

Redis配置类
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;@Configuration
public class RedisConfig {@Beanpublic RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {RedisTemplate<String, Object> template = new RedisTemplate<>();template.setConnectionFactory(factory);template.setKeySerializer(new StringRedisSerializer());template.setValueSerializer(new StringRedisSerializer());return template;}
}

解释

  1. 配置RedisTemplate来处理Redis操作,设置键和值的序列化器为 StringRedisSerializer 以便于存储和读取字符串类型的数据。
服务类
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import java.util.concurrent.TimeUnit;@Service
public class ValidationService {private static final String NAME_ID_KEY = "name_id:";private static final String CARD_ERROR_KEY = "card_error:";private static final int LOCK_TIME = 5; // minutesprivate static final int MAX_ATTEMPTS = 5;@Autowiredprivate RedisTemplate<String, Object> redisTemplate;public boolean validateNameAndId(String name, String id, String correctName, String correctId) {if (name.equals(correctName) && id.equals(correctId)) {return true;}if (!name.equals(correctName)) {throw new IllegalArgumentException("姓名输入错误,请重新输入");}if (!id.equals(correctId)) {throw new IllegalArgumentException("工号输入错误,请重新输入");}return false;}public void validateCard(String serialNumber, String inputCard, String correctCard) {String cardErrorKey = CARD_ERROR_KEY + serialNumber;// 检查是否已锁定if (Boolean.TRUE.equals(redisTemplate.hasKey(cardErrorKey)) && redisTemplate.getExpire(cardErrorKey) > 0) {throw new IllegalStateException("密码错误次数过多,请稍后再试");}// 获取当前错误次数int attempts = redisTemplate.opsForValue().get(cardErrorKey) == null ? 0 : (int) redisTemplate.opsForValue().get(cardErrorKey);if (!inputCard.equals(correctCard)) {attempts++;if (attempts >= MAX_ATTEMPTS) {// 超过最大尝试次数,锁定序列号redisTemplate.opsForValue().set(cardErrorKey, attempts, LOCK_TIME, TimeUnit.MINUTES);throw new IllegalStateException("密码错误次数过多,请稍后再试");} else {// 更新错误次数redisTemplate.opsForValue().set(cardErrorKey, attempts);throw new IllegalArgumentException(String.format("卡密已输入错误%d次,超过%d次将锁定", attempts, MAX_ATTEMPTS));}} else {// 验证成功,清除错误次数redisTemplate.delete(cardErrorKey);}}
}

解释

  1. validateNameAndId方法:校验用户输入的姓名和工号是否与正确的姓名和工号匹配。如果不匹配,抛出适当的异常。
  2. validateCard方法:校验卡密是否正确。使用Redis记录每个序列号的错误次数,并在错误次数达到最大尝试次数时锁定序列号一定时间。
    • attempts变量用于记录当前错误次数。如果Redis中不存在该键,则初始化为0。
    • 如果输入的卡密不正确,错误次数增加:
      • 如果错误次数达到或超过最大尝试次数(MAX_ATTEMPTS),则设置锁定时间(LOCK_TIME),并抛出 IllegalStateException
      • 否则,更新错误次数并抛出 IllegalArgumentException,提示错误次数。

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • WUP-MY-LABEL-PRINTER 旻佑热敏打印机标签打印uniapp插件使用说明
  • 革新测试管理:集远程、协同、自动化于一身的统一测试管理平台
  • Depth Anything: Unleashing the Power of Large-Scale Unlabeled Data精读
  • Prometheus+Grafana保姆笔记(2)——监控Spring Boot微服务程序
  • 基于VS2022+Qt5+C++的串口助手开发
  • MySQL:复杂查询(二)——联合查询02
  • C语言之指针高级--指针操作二维整型、字符型数组、函数指针
  • vscode远程开发
  • C++:std::memory_order_relaxed(宽松内存序)
  • [Vue3] 9 其它API
  • Elasticsearch 搜索高亮功能及示例
  • 谷粒商城实战笔记-179~183-商城业务-检索服务-SearchRequest和SearchResponse构建
  • js中的promise、async/await 用法,详解async、await 语法糖,js中的宏任务和微任务(保姆级教程二)
  • vscode的C/C++环境配置和调试技巧
  • 基于Transformer机制的AI现阶段可能已达峰值
  • -------------------- 第二讲-------- 第一节------在此给出链表的基本操作
  • [译] React v16.8: 含有Hooks的版本
  • 《网管员必读——网络组建》(第2版)电子课件下载
  • Create React App 使用
  • Effective Java 笔记(一)
  • Git 使用集
  • JavaScript类型识别
  • java中具有继承关系的类及其对象初始化顺序
  • js 实现textarea输入字数提示
  • js数组之filter
  • tensorflow学习笔记3——MNIST应用篇
  • 码农张的Bug人生 - 见面之礼
  • 什么软件可以提取视频中的音频制作成手机铃声
  • 新书推荐|Windows黑客编程技术详解
  • 用Python写一份独特的元宵节祝福
  • 源码之下无秘密 ── 做最好的 Netty 源码分析教程
  • kubernetes资源对象--ingress
  • # Swust 12th acm 邀请赛# [ K ] 三角形判定 [题解]
  • (二)springcloud实战之config配置中心
  • (十二)python网络爬虫(理论+实战)——实战:使用BeautfulSoup解析baidu热搜新闻数据
  • (四)Tiki-taka算法(TTA)求解无人机三维路径规划研究(MATLAB)
  • (心得)获取一个数二进制序列中所有的偶数位和奇数位, 分别输出二进制序列。
  • (转)Oracle存储过程编写经验和优化措施
  • (转)用.Net的File控件上传文件的解决方案
  • .NET 8 中引入新的 IHostedLifecycleService 接口 实现定时任务
  • .NET C# 使用 iText 生成PDF
  • .net core 控制台应用程序读取配置文件app.config
  • .NET Core使用NPOI导出复杂,美观的Excel详解
  • .Net FrameWork总结
  • .NET/C# 解压 Zip 文件时出现异常:System.IO.InvalidDataException: 找不到中央目录结尾记录。
  • .NET程序集编辑器/调试器 dnSpy 使用介绍
  • ??在JSP中,java和JavaScript如何交互?
  • [BT]BUUCTF刷题第4天(3.22)
  • [BZOJ4566][HAOI2016]找相同字符(SAM)
  • [C#] 我的log4net使用手册
  • [C++]打开新世界的大门之C++入门
  • [Django开源学习 1]django-vue-admin
  • [Go 微服务] Kratos 验证码业务
  • [IDF]聪明的小羊
  • [JAVASE] 异常 与 SE阶段知识点补充