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.mzph.cn/news/877405.shtml

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

相关文章

阿里云账户注册与实名认证详细教程

在开始使用阿里云服务之前&#xff0c;您需要先有一个阿里云账号&#xff0c;拥有阿里云账号后&#xff0c;您可以选购和使用云产品和服务。如果您没有阿里云账号&#xff0c;需要先注册一个阿里云账号。 说明 一个手机号码下最多可以注册6个阿里云账号。如果您的手机号码已经…

一分钟了解VMware虚拟机三种网络模式区别

VMware虚拟机提供了三种主要的网络模式&#xff0c;分别是桥接模式&#xff08;Bridged Mode&#xff09;、网络地址转换模式&#xff08;NAT Mode&#xff09;和仅主机模式&#xff08;Host-Only Mode&#xff09;。这三种模式各有其特点和适用场景&#xff0c;以下是对它们之…

Perfectly Clear WorkBench中文绿色版,让每一张照片都完美无瑕

软件简介 你是否曾经为了一张不完美的照片而感到遗憾&#xff1f;是否曾经因为照片中的小瑕疵而不得不花费大量时间进行后期处理&#xff1f;现在&#xff0c;有了Perfectly Clear WorkBench&#xff0c;这些问题都将迎刃而解。作为全球领先的智能图像校正技术商推出的图像清晰…

jvm实战

一、查看JVM内存使用状况 jps 查看本地正在运行的java进程和进程ID(pid) win10报jps不是内部或外部命令,也不是可运行的程序或批处理文件解决?将用户变量和系统变量的Path都追加2个bin。 jinfo jinfo pid 查看指定pid的所有JVM信息jinfo -flags pid 查询虚拟机运行参数…

【Go - mongodb - bson / schema】

Bson是什么 bson 是 MongoDB 使用的一种二进制编码格式&#xff0c;全称为 Binary JSON。它用于存储和传输 JSON 风格的文档数据。bson 提供了一种高效的方式来表示 JSON 数据&#xff0c;同时支持更多的数据类型&#xff0c;例如日期和二进制数据。 在 Go 语言中&#xff0c…

低代码开发平台:加速企业数字化转型的利器

前言 在软件开发领域&#xff0c;传统的编码方式往往复杂且耗时&#xff0c;对技术团队的技能要求高。随着企业数字化转型的加速&#xff0c;低代码开发平台作为一种新兴的解决方案&#xff0c;逐渐成为许多组织提升开发效率、降低技术门槛的利器。本文将深入探讨低代码开发的…

【Drools】(三)基于业务数据动态调用 DRL 规则文件:详细实现与测试指南

基于业务数据动态调用 DRL 规则文件&#xff1a;详解与实战 在业务规则管理中&#xff0c;DRL 文件&#xff08;Drools Rule Language 文件&#xff09;用于定义和执行业务规则。通过动态调用 DRL 文件&#xff0c;我们可以根据不同的业务场景灵活配置和执行定制化的规则&…

【中项】系统集成项目管理工程师-第8章 信息安全工程-8.3工程体系架构

前言&#xff1a;系统集成项目管理工程师专业&#xff0c;现分享一些教材知识点。觉得文章还不错的喜欢点赞收藏的同时帮忙点点关注。 软考同样是国家人社部和工信部组织的国家级考试&#xff0c;全称为“全国计算机与软件专业技术资格&#xff08;水平&#xff09;考试”&…

MongoDB 基础知识

一、为什么学习MongoDB MongoDB解决Mysql 的“三高”问题&#xff1a; 1.对数据库高并发写入需求 2.对海量数据高效率存储访问需求 3.对数据库高扩展和高可用的需求 MongoDB 实际应用&#xff1a; 1.社交场景&#xff0c;比如朋友圈&#xff0c;附近的人的地点的存储 2.…

Python for循环迭代原理(迭代器 Iterator)

在使用Python时&#xff0c;我们经常会使用for循环来访问容器对象&#xff08;列表、字符、字典等&#xff09;中的元素。其幕后实际是通过迭代协议来完成的&#xff0c;迭代是一种依次访问对象中元素的方式&#xff0c;for循环在对象上调用iter()函数生成一个迭代器&#xff0…

wc -l 统计文件中的行数

wc -l 是一个常用的命令行工具&#xff0c;用于统计文件中的行数。它的使用格式是&#xff1a; wc -l [文件名] 主要用途是计算指定文件中的行数。例如&#xff0c;如果有一个名为 example.txt 的文件&#xff0c;要查看它有多少行&#xff0c;可以运行&#xff1a; wc -l exam…

16 html网页服务和nginx服务

第十六次7.29 1.静态页面 1安装httpd [rootweb ~]# yum -y install httpd 2.真机访问页面 [rootweb html]# echo "静态html文件" > index.html 传入照片再次访问 静态资源&#xff0c;根据开发着保存在项目资源目录中的路径访问静态页面的资源 2.Apache 1.安…

【Docker】Namespace 空间隔离实战

一、实战目的 了解隔离能力并不是 Docker 提供的&#xff0c;而是操作系统内核提供基本能力。 二、基础知识 1、dd 命令详解 Linux dd 命令用于读取、转换并输出数据。 dd 可从标准输入或文件中读取数据&#xff0c;根据指定的格式来转换数据&#xff0c;再输出到文件、…

淘宝商家电话采集 淘宝店铺爬虫软件使用教程

淘宝商家电话采集&#xff1a;淘宝店铺爬虫软件使用教程 淘宝作为中国最大的电子商务平台之一&#xff0c;拥有众多的商家和店铺。有时候我们需要获取特定店铺的联系电话&#xff0c;以便进行合作洽谈或者其他目的。本文将介绍如何使用Python编写一个淘宝店铺爬虫软件来采集商…

有效组织离散变量:指针数组在C语言中的应用

把离散变量组织起来&#xff0c;访问起来更加方便&#xff0c;无需一个个变量单独赋值。 如modbus读写reg&#xff0c; 把a\b\c\d实时变化分散的变量组织成一个数组reg&#xff0c;方便获取 相当于变量的内存地址池 int main() {int a 10, b 20, c 30, d 40;int i;int *re…

Vue3----扩展 element Plug card

扩展 element Plug card 增加全屏&#xff0c;折叠操作项 核心代码 <template><div class"cc-card-component"><el-card v-if"state.isShow" :class"state.class" :bodyStyle"bodyStyle" :shadow"props.shadow…

英语:四、冠词

1、冠词的概述 &#xff08;1&#xff09;冠词的分类 根据冠词的用法&#xff0c;它可以分为定冠词、不定冠词和零冠词。 定冠词 the 不定冠词 a an 零冠词 名词前面没有冠词 &#xff08;2&#xff09;冠词的位置 a、放在名词之前 一般情况下&#xff0c;冠词置于…

Vmwar保姆级安装与配置

文章目录 一、官方下载1.访问VMware官方网站&#xff1a;2.选择产品&#xff1a;3.下载安装包&#xff1a; 二、VMware的安装1.运行安装程序2.选择安装位置3.选择安装选项4.完成安装 三、启动VMware Workstation Pro并配置虚拟机1.创建新的虚拟机&#xff1a;2.配置虚拟机硬件 …

中间件 - 使用Eureka进行微服务注册与发现

作者&#xff1a;逍遥Sean 简介&#xff1a;一个主修Java的Web网站\游戏服务器后端开发者 主页&#xff1a;https://blog.csdn.net/Ureliable 觉得博主文章不错的话&#xff0c;可以三连支持一下~ 如有疑问和建议&#xff0c;请私信或评论留言&#xff01; 前言 在微服务架构中…

【C#】.net core 6.0 webapi 使用core版本的NPOI的Excel读取数据以及保存数据

欢迎来到《小5讲堂》 这是《C#》系列文章&#xff0c;每篇文章将以博主理解的角度展开讲解。 温馨提示&#xff1a;博主能力有限&#xff0c;理解水平有限&#xff0c;若有不对之处望指正&#xff01; 目录 背景读取并保存NPOI信息NPOI 插件介绍基本功能示例代码写入 Excel 文件…