SpringBoot 整合 Redis 实现验证码登录功能

一、整合Redis

  • pom.xml中添加Redis相关依赖;
<!--Spring Data Redis依赖配置-->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
  • 修改配置文件application.yml,添加Redis的连接配置;
spring:redis:host: localhost # Redis服务器地址database: 0 # Redis数据库索引(默认为0)port: 6379 # Redis服务器连接端口password: # Redis服务器连接密码(默认为空)lettuce:pool:max-active: 8 # 连接池最大连接数max-idle: 8 # 连接池最大空闲连接数min-idle: 0 # 连接池最小空闲连接数max-wait: -1ms # 连接池最大阻塞等待时间,负值表示没有限制
  • 修改配置文件application.yml,添加Redis中自定义key的配置;
# 自定义redis key
redis:key:prefix:authCode: "portal:authCode:"expire:authCode: 120 # 验证码超期时间
  • 添加Redis的Java配置,配置好RedisTemplate;
/*** @description Redis配置类*/
@EnableCaching
@Configuration
public class RedisConfig {/*** redis数据库自定义key*/public  static final String REDIS_KEY_DATABASE="mall";@Beanpublic RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {RedisSerializer<Object> serializer = redisSerializer();RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();redisTemplate.setConnectionFactory(redisConnectionFactory);redisTemplate.setKeySerializer(new StringRedisSerializer());redisTemplate.setValueSerializer(serializer);redisTemplate.setHashKeySerializer(new StringRedisSerializer());redisTemplate.setHashValueSerializer(serializer);redisTemplate.afterPropertiesSet();return redisTemplate;}@Beanpublic RedisSerializer<Object> redisSerializer() {//创建JSON序列化器Jackson2JsonRedisSerializer<Object> serializer = new Jackson2JsonRedisSerializer<>(Object.class);ObjectMapper objectMapper = new ObjectMapper();objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);//必须设置,否则无法将JSON转化为对象,会转化成Map类型objectMapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance,ObjectMapper.DefaultTyping.NON_FINAL);serializer.setObjectMapper(objectMapper);return serializer;}@Beanpublic RedisCacheManager redisCacheManager(RedisConnectionFactory redisConnectionFactory) {RedisCacheWriter redisCacheWriter = RedisCacheWriter.nonLockingRedisCacheWriter(redisConnectionFactory);//设置Redis缓存有效期为1天RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig().serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer())).entryTtl(Duration.ofDays(1));return new RedisCacheManager(redisCacheWriter, redisCacheConfiguration);}}
  • 添加RedisService接口用于定义一些常用Redis操作;
/*** @description redis操作Service*/
public interface RedisService {/*** 保存属性*/void set(String key, Object value, long time);/*** 保存属性*/void set(String key, Object value);/*** 获取属性*/Object get(String key);/*** 删除属性*/Boolean del(String key);/*** 批量删除属性*/Long del(List<String> keys);/*** 设置过期时间*/Boolean expire(String key, long time);/*** 获取过期时间*/Long getExpire(String key);/*** 判断是否有该属性*/Boolean hasKey(String key);/*** 按delta递增*/Long incr(String key, long delta);/*** 按delta递减*/Long decr(String key, long delta);/*** 获取Hash结构中的属性*/Object hGet(String key, String hashKey);/*** 向Hash结构中放入一个属性*/Boolean hSet(String key, String hashKey, Object value, long time);/*** 向Hash结构中放入一个属性*/void hSet(String key, String hashKey, Object value);/*** 直接获取整个Hash结构*/Map<Object, Object> hGetAll(String key);/*** 直接设置整个Hash结构*/Boolean hSetAll(String key, Map<String, Object> map, long time);/*** 直接设置整个Hash结构*/void hSetAll(String key, Map<String, Object> map);/*** 删除Hash结构中的属性*/void hDel(String key, Object... hashKey);/*** 判断Hash结构中是否有该属性*/Boolean hHasKey(String key, String hashKey);/*** Hash结构中属性递增*/Long hIncr(String key, String hashKey, Long delta);/*** Hash结构中属性递减*/Long hDecr(String key, String hashKey, Long delta);/*** 获取Set结构*/Set<Object> sMembers(String key);/*** 向Set结构中添加属性*/Long sAdd(String key, Object... values);/*** 向Set结构中添加属性*/Long sAdd(String key, long time, Object... values);/*** 是否为Set中的属性*/Boolean sIsMember(String key, Object value);/*** 获取Set结构的长度*/Long sSize(String key);/*** 删除Set结构中的属性*/Long sRemove(String key, Object... values);/*** 获取List结构中的属性*/List<Object> lRange(String key, long start, long end);/*** 获取List结构的长度*/Long lSize(String key);/*** 根据索引获取List中的属性*/Object lIndex(String key, long index);/*** 向List结构中添加属性*/Long lPush(String key, Object value);/*** 向List结构中添加属性*/Long lPush(String key, Object value, long time);/*** 向List结构中批量添加属性*/Long lPushAll(String key, Object... values);/*** 向List结构中批量添加属性*/Long lPushAll(String key, Long time, Object... values);/*** 从List结构中移除属性*/Long lRemove(String key, long count, Object value);
}
  • 注入RedisTemplate,实现RedisService接口。
/*** @description redis操作实现类*/
@Service
public class RedisServiceImpl implements RedisService {@Autowiredprivate RedisTemplate<String, Object> redisTemplate;@Overridepublic void set(String key, Object value, long time) {redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);}@Overridepublic void set(String key, Object value) {redisTemplate.opsForValue().set(key, value);}@Overridepublic Object get(String key) {return redisTemplate.opsForValue().get(key);}@Overridepublic Boolean del(String key) {return redisTemplate.delete(key);}@Overridepublic Long del(List<String> keys) {return redisTemplate.delete(keys);}@Overridepublic Boolean expire(String key, long time) {return redisTemplate.expire(key, time, TimeUnit.SECONDS);}@Overridepublic Long getExpire(String key) {return redisTemplate.getExpire(key, TimeUnit.SECONDS);}@Overridepublic Boolean hasKey(String key) {return redisTemplate.hasKey(key);}@Overridepublic Long incr(String key, long delta) {return redisTemplate.opsForValue().increment(key, delta);}@Overridepublic Long decr(String key, long delta) {return redisTemplate.opsForValue().increment(key, -delta);}@Overridepublic Object hGet(String key, String hashKey) {return redisTemplate.opsForHash().get(key, hashKey);}@Overridepublic Boolean hSet(String key, String hashKey, Object value, long time) {redisTemplate.opsForHash().put(key, hashKey, value);return expire(key, time);}@Overridepublic void hSet(String key, String hashKey, Object value) {redisTemplate.opsForHash().put(key, hashKey, value);}@Overridepublic Map<Object, Object> hGetAll(String key) {return redisTemplate.opsForHash().entries(key);}@Overridepublic Boolean hSetAll(String key, Map<String, Object> map, long time) {redisTemplate.opsForHash().putAll(key, map);return expire(key, time);}@Overridepublic void hSetAll(String key, Map<String, Object> map) {redisTemplate.opsForHash().putAll(key, map);}@Overridepublic void hDel(String key, Object... hashKey) {redisTemplate.opsForHash().delete(key, hashKey);}@Overridepublic Boolean hHasKey(String key, String hashKey) {return redisTemplate.opsForHash().hasKey(key, hashKey);}@Overridepublic Long hIncr(String key, String hashKey, Long delta) {return redisTemplate.opsForHash().increment(key, hashKey, delta);}@Overridepublic Long hDecr(String key, String hashKey, Long delta) {return redisTemplate.opsForHash().increment(key, hashKey, -delta);}@Overridepublic Set<Object> sMembers(String key) {return redisTemplate.opsForSet().members(key);}@Overridepublic Long sAdd(String key, Object... values) {return redisTemplate.opsForSet().add(key, values);}@Overridepublic Long sAdd(String key, long time, Object... values) {Long count = redisTemplate.opsForSet().add(key, values);expire(key, time);return count;}@Overridepublic Boolean sIsMember(String key, Object value) {return redisTemplate.opsForSet().isMember(key, value);}@Overridepublic Long sSize(String key) {return redisTemplate.opsForSet().size(key);}@Overridepublic Long sRemove(String key, Object... values) {return redisTemplate.opsForSet().remove(key, values);}@Overridepublic List<Object> lRange(String key, long start, long end) {return redisTemplate.opsForList().range(key, start, end);}@Overridepublic Long lSize(String key) {return redisTemplate.opsForList().size(key);}@Overridepublic Object lIndex(String key, long index) {return redisTemplate.opsForList().index(key, index);}@Overridepublic Long lPush(String key, Object value) {return redisTemplate.opsForList().rightPush(key, value);}@Overridepublic Long lPush(String key, Object value, long time) {Long index = redisTemplate.opsForList().rightPush(key, value);expire(key, time);return index;}@Overridepublic Long lPushAll(String key, Object... values) {return redisTemplate.opsForList().rightPushAll(key, values);}@Overridepublic Long lPushAll(String key, Long time, Object... values) {Long count = redisTemplate.opsForList().rightPushAll(key, values);expire(key, time);return count;}@Overridepublic Long lRemove(String key, long count, Object value) {return redisTemplate.opsForList().remove(key, count, value);}
}

二、实现验证码逻辑

        这里以短信验证码的存储验证为例,具体逻辑如下:生成验证码时,将自定义的Redis键值加上手机号生成一个Redis的key,以验证码为value存入到Redis中,并设置过期时间为自己配置的时间(这里为120s)。校验验证码时根据手机号码来获取Redis里面存储的验证码,并与传入的验证码进行比对。

  • 添加UmsMemberController类,添加根据电话号码获取验证码的接口和校验验证码的接口;
/*** @description 会员登录注册管理Controller*/
@Controller
@Api(tags = "UmsMemberController")
@Tag(name = "UmsMemberController", description = "会员登录注册管理")
@RequestMapping("/sso")
public class UmsMemberController {@Autowiredprivate UmsMemberService memberService;@ApiOperation("获取验证码")@RequestMapping(value = "/getAuthCode", method = RequestMethod.GET)@ResponseBodypublic CommonResult getAuthCode(@RequestParam String telephone) {return memberService.generateAuthCode(telephone);}@ApiOperation("判断验证码是否正确")@RequestMapping(value = "/verifyAuthCode", method = RequestMethod.POST)@ResponseBodypublic CommonResult updatePassword(@RequestParam String telephone,@RequestParam String authCode) {return memberService.verifyAuthCode(telephone,authCode);}
}
  • 添加UmsMemberService接口;
/*** @description 会员管理Service*/
public interface UmsMemberService {/*** 生成验证码*/CommonResult generateAuthCode(String telephone);/*** 判断验证码和手机号码是否匹配*/CommonResult verifyAuthCode(String telephone, String authCode);}
  • 添加UmsMemberService接口的实现类UmsMemberServiceImpl。
/*** @description 会员管理Service实现类*/
@Service
public class UmsMemberServiceImpl implements UmsMemberService {@Autowiredprivate RedisService redisService;@Value("${redis.key.prefix.authCode}")private String REDIS_KEY_PREFIX_AUTH_CODE;@Value("${redis.key.expire.authCode}")private Long AUTH_CODE_EXPIRE_SECONDS;@Overridepublic CommonResult generateAuthCode(String telephone) {StringBuilder sb = new StringBuilder();Random random = new Random();for (int i = 0; i < 6; i++) {sb.append(random.nextInt(10));}//验证码绑定手机号并存储到redisredisService.set(REDIS_KEY_PREFIX_AUTH_CODE + telephone, sb.toString());redisService.expire(REDIS_KEY_PREFIX_AUTH_CODE + telephone, AUTH_CODE_EXPIRE_SECONDS);return CommonResult.success(sb.toString(), "获取验证码成功");}//对输入的验证码进行校验@Overridepublic CommonResult verifyAuthCode(String telephone, String authCode) {if (StrUtil.isEmpty(authCode)) {return CommonResult.failed("请输入验证码");}String realAuthCode = (String) redisService.get(REDIS_KEY_PREFIX_AUTH_CODE + telephone);boolean result = authCode.equals(realAuthCode);if (result) {return CommonResult.success(null, "验证码校验成功");} else {return CommonResult.failed("验证码不正确");}}}

三、使用 Swagger 的界面测试接口

访问Swagger的API文档对接口进行测试,访问地址:地址http://localhost:8080/swagger-ui/

 

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

永结无间Ⅵ--第一支AI测试团队

我们都梦想拥有一支 AI 测试团队。每个工程团队都应该测试他们的应用程序&#xff0c;但测试速度慢、成本高&#xff0c;而且很少能提供足够的覆盖范围。大多数团队几乎没有测试。专门的测试人员或供应商往往会忽略测试的许多方面。测试人员希望专注于测试中有趣且重要的方面&a…

WPF的MVVM架构:如何通过数据绑定简化UI逻辑

WPF的MVVM架构&#xff1a;如何通过数据绑定简化UI逻辑 目录 MVVM模式概述数据绑定在MVVM中的作用实现MVVM模式的步骤MVVM模式中的常见问题与解决方案实践示例总结 MVVM模式概述 MVVM&#xff08;Model-View-ViewModel&#xff09;是一种设计模式&#xff0c;用于WPF应用程序…

Navidrome音乐服务器 + 音流APP = 释放你的手机空间

20240727 By wdhuag 目录 前言&#xff1a; 参考&#xff1a; Navidrome音乐服务器 Demo试用&#xff1a; 支持多平台&#xff1a; 下载&#xff1a; 修改配置&#xff1a; 设置用NSSM成服务启动&#xff1a; 服务器本地访问网址&#xff1a; 音流 歌词封面API&am…

HTML+CSS+JavaScript实现烟花绽放的效果源码

源码 复制粘贴代码 在同级别下放一张图片fire.png接可以了 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><…

2024年7月23日~2024年7月29日周报

目录 一、前言 二、完成情况 2.1 一种具有边缘增强特点的医学图像分割网络 2.2 融合边缘增强注意力机制和 U-Net 网络的医学图像分割 2.3 遇到的困难 三、下周计划 一、前言 上周参加了一些师兄师姐的论文讨论会议&#xff0c;并完成了初稿。 本周继续修改论文&#xff0…

【Qt】QLCDNumberQProgressBarQCalendarWidget

目录 QLCDNumber 倒计时小程序 相关属性 QProgressBar 进度条小程序 相关设置 QLCDNumber QLCDNumber是Qt框架中用于显示数字或计数值的小部件。通常用于显示整数值&#xff0c;例如时钟、计时器、计数器等 常用属性 属性说明intValueQLCDNumber显示的初始值(int类型)va…

Hbase简介和快速入门

一 Hbase简介 1 HBase定义 Apache HBase™ 是以hdfs为数据存储的&#xff0c;一种分布式、可扩展的NoSQL数据库。 2 HBase数据模型 HBase的设计理念依据Google的BigTable论文&#xff0c;论文中对于数据模型的首句介绍。Bigtable 是一个稀疏的、分布式的、持久的多维排序map…

【JAVA学习笔记】找不到依赖项 ‘org.springframework.boot:spring-boot-starter-web:3.0.5‘

如果环境都是跟着教程配的话&#xff0c;并且上网搜了一圈询问gpt都没发现对应长得像的错误&#xff0c;那么试试刷新一下Maven项目&#xff0c;可能问题就自己解决了。如果这样解决不了再查到底是什么地方没有配置对。 &#xff08;我第一次遇到这个问题的时候搜了半天都不知…

【ROS 最简单教程 002/300】ROS 集成开发环境安装 (虚拟机版): Noetic

&#x1f497; 有遇到安装问题可以留言呀 ~ 当时踩了挺多坑&#xff0c;能帮忙解决的我会尽力 &#xff01; 1. 安装操作系统环境 Linux ❄️ VM / VirtualBox Ubuntu20.04 &#x1f449; 保姆级图文安装教程指路&#xff0c;有经验的话 可以用如下资源自行安装 ITEMREFERENCE…

【Windows】Mountain Duck(FTP服务器管理工具)软件介绍

软件介绍 Mountain Duck是一款基于Cyberduck开发的应用程序&#xff0c;它允许用户通过FTP、SFTP、WebDAV、S3和OpenStack Swift等协议连接到云存储和远程服务器&#xff0c;并在本地文件浏览器中以熟悉的方式访问和管理这些文件。 功能特点 支持多种协议: Mountain Duck支持…

Unity和WebGL交互-2024/7/30

进入项目 1 新建一个.jslib的文件 2 放到项目内Plugins文件夹下 3 可以用vscode之类的编译器打开这个文件 编写内容 mergeInto(LibraryManager.library, {// 方法名必须和c#中的相同// 有参数 需要用UTF8ToString&#xff08;&#xff09;OnInitSDK:function(str) {window.OnIn…

vue自写组件可输入,可下拉选择,因为el-autocomplete数据多了会卡

<!-- 引入组件 --><AutoCompletev-model"scope.row.strreceivername":lngemployeeid"scope.row.lngreceiverid"select"handleSelect($event,scope.row)"/> methods:{handleSelect(item, row) {row.lngreceiverid item.lngemployeei…

项目实战——外挂开发(30小时精通C++和外挂实战)

项目实战——外挂开发&#xff08;30小时精通C和外挂实战&#xff09; 外挂开发1-监控游戏外挂开发2-秒杀僵尸外挂开发3-阳光地址分析外挂开发4-模拟阳光外挂开发5-无限阳光 外挂开发1-监控游戏 外挂的本质 有两种方式 1&#xff0c;修改内存中的数据 2&#xff0c;更改内存中…

从零开始学习网络安全渗透测试之基础入门篇——(二)Web架构前后端分离站Docker容器站OSS存储负载均衡CDN加速反向代理WAF防护

Web架构 Web架构是指构建和管理Web应用程序的方法和模式。随着技术的发展&#xff0c;Web架构也在不断演进。当前&#xff0c;最常用的Web架构包括以下几种&#xff1a; 单页面应用&#xff08;SPA&#xff09;&#xff1a; 特点&#xff1a;所有用户界面逻辑和数据处理都包含…

火山引擎VeDI数据技术分享:两个步骤,为Parquet降本提效

更多技术交流、求职机会&#xff0c;欢迎关注字节跳动数据平台微信公众号&#xff0c;回复【1】进入官方交流群 作者&#xff1a;王恩策、徐庆 火山引擎 LAS 团队 火山引擎数智平台 VeDI 是火山引擎推出的新一代企业数据智能平台&#xff0c;基于字节跳动数据平台多年的“数据…

[Javascript】前端面试基础3【每日学习并更新10】

Web开发中会话跟踪的方法有那些 cookiesessionurl重写隐藏inputip地址 JS基本数据类型 String&#xff1a;用于表示文本数据。Number&#xff1a;用于表示数值&#xff0c;包括整数和浮点数。BigInt&#xff1a;用于表示任意精度的整数。Boolean&#xff1a;用于表示逻辑值…

认证授权概述和SpringSecurity安全框架快速入门

1. 认证授权的概述 1.1 什么是认证 进入移动互联网时代&#xff0c;大家每天都在刷手机&#xff0c;常用的软件有微信、支付宝、头条、抖音等 以微信为例说明认证的相关基本概念。在初次使用微信前需要注册成为微信用户&#xff0c;然后输入账号和密码即可登录微信&#xff0c…

git 推送时出现错误 Locking support detected on remote “origin“

背景&#xff1a;代码托管是局域网搭建的gitlab 按照提示配置 lfs.locksverify true 还是没有用。 网上搜索了一番&#xff0c;其中有人提到可能时服务器磁盘满了&#xff0c;连到服务器上 df -h 查看&#xff0c; 发现根目录已经写满了&#xff1a; 使用命令行&#xff1a; d…

scipy.fft.fft函数与scipy.fft.rfft函数的异同

import numpy as np from scipy import signal import matplotlib.pyplot as plt思路&#xff1a;1&#xff09;先利用fft计算得出其幅频值2&#xff09;在利用rfft计算得出其幅频值&#xff0c;看1&#xff09;和2&#xff09;那个能还原出信号的原始幅值# 生成一个示例信号 n…

c#实际开发长到的知识

基础科普: 个人建议先把rotion的库导入进来再操作,具体需要导入的库有,helper库包含了modbus通讯封装好的模块,而mvvm则可以用来做设计mvvm模块,你可以使用里面封装好的实现方法,用起来特别简单更容易实现其中的操作,但是我担心那天被卡脖子了啊啊啊,要是我罗工把库下…