Spring Boot 3.x 基于 Redis 实现邮箱验证码认证
文章目录
- 依赖配置
- 开启 QQ 邮箱 SMTP 服务
- 配置文件
- 代码实现
- 验证码服务
- 邮件服务
- 接口实现
- 执行流程
依赖配置
<dependencies> <!-- Spring Boot Starter Web --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- Redis 集成依赖 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> <version>3.4.2</version> </dependency> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-pool2</artifactId> <version>2.11.1</version> </dependency> <dependency> <groupId>io.lettuce</groupId> <artifactId>lettuce-core</artifactId> <version>6.3.2.RELEASE</version> </dependency><!-- 邮件发送支持 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-mail</artifactId> </dependency> <!-- 验证码生成工具 --> <dependency> <groupId>commons-lang</groupId> <artifactId>commons-lang</artifactId> <version>2.6</version> </dependency>
</dependencies>
开启 QQ 邮箱 SMTP 服务
- 打开浏览器,登录到 QQ 邮箱。
- 点击左上角的齿轮按钮,进入设置页面,见下图:
4. 在设置中找到“第三方服务”,激活 IMAP/SMTP(默认为禁用),并生成独立的 SMTP 授权码。 
配置文件
spring: data: redis: host: your_redis_hostport: your_redis_port # 通常为6379password: your_redis_passwordlettuce: pool: max-active: 8 # 最大连接数 max-idle: 8 # 最大空闲连接数 min-idle: 0 # 最小空闲连接数 max-wait: 100 # 连接等待时间 mail: host: smtp.qq.com port: 465 username: your_qq_account@qq.compassword: 111 # 输入 QQ 邮箱的授权码properties: mail: smtp: ssl: enable: true # QQ 邮箱需要开启 SSLauth: true
代码实现
验证码服务
使用 Redis 缓存验证码并实现验证码的校验功能:
@Service
public class CaptchaService { @Autowired private StringRedisTemplate redisTemplate; /** * 生成验证码 * @param email 目标邮箱 * @return 生成的验证码 */ public String generateCaptcha(String email) { // 生成验证码 String code = RandomStringUtils.randomNumeric(6); redisTemplate.opsForValue().set( "CAPTCHA:" + email, code, Duration.ofMinutes(5) // 验证码有效期为5分钟 ); return code; } /** * 验证码校验 * @param email 邮箱 * @param code 验证码 * @return 是否验证通过 */ public boolean validateCaptcha(String email, String code) { String captcha = redisTemplate.opsForValue().get("CAPTCHA:" + email); return captcha != null && captcha.equals(code); }
}
邮件服务
@Service
public class EmailService { @Autowired private JavaMailSender mailSender; /** * 发送验证码邮件 * @param email 收件人邮箱 * @param authCode 验证码 */ public void sendCaptchaEmail(String email, String authCode) { SimpleMailMessage message = new SimpleMailMessage(); message.setFrom("your_qq_account@qq.com"); message.setTo(email); message.setSubject("验证码"); message.setText("您的验证码是:" + authCode + ",有效期为5分钟"); mailSender.send(message); }
}
接口实现
@RestController
public class AuthController { @Autowired private UserService userService; @Autowired private CaptchaService captchaService; @Autowired private EmailService emailService; /** * 注册接口 * @param userDTO 用户信息 * @param captcha 验证码 * @return 注册结果 */ @PostMapping("/register") public Result register(@RequestBody UserDTO userDTO, @RequestParam String captcha) { if (!captchaService.validateCaptcha(userDTO.getEmail(), captcha)) { return Result.error("验证码错误"); } userService.register(userDTO); return Result.success(); } /** * 登录接口 * @param userDTO 用户信息 * @return 登录结果 */ @PostMapping("/login") public Result login(@RequestBody UserDTO userDTO) { User user = userService.login(userDTO); if (user == null) { return Result.error("用户不存在"); } // 登录成功,生成 JWT 令牌 Map<String, Object> claims = new HashMap<>(); claims.put("userId", user.getId()); String token = JwtUtils.createJWT("secretKey", 60000, claims); UserVO userVO = new UserVO(); BeanUtils.copyProperties(user, userVO); LoginResponse loginResponse = new LoginResponse(userVO, token); return Result.success(loginResponse); } /** * 发送验证码接口 * @param email 邮箱地址 * @return 发送结果 */ @PostMapping("/send-code") public Result sendCode(@RequestParam String email) throws MessagingException { // 校验邮箱格式if (!RegexUtils.isEmailValid(email)) { return Result.error("邮箱格式非法"); } String code = captchaService.generateCaptcha(email); emailService.sendCaptchaEmail(email, code); return Result.success(); }
}
执行流程
- 用户输入邮箱,调用
/send-code接口获取验证码。 - 用户填写验证码并调用
/register接口进行注册。 - 系统校验验证码,验证成功则注册,失败则返回错误信息。
相关文章:
Spring Boot 3.x 基于 Redis 实现邮箱验证码认证
文章目录 依赖配置开启 QQ 邮箱 SMTP 服务配置文件代码实现验证码服务邮件服务接口实现执行流程 依赖配置 <dependencies> <!-- Spring Boot Starter Web --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spr…...
车载测试:智能座舱测试中多屏联动与语音交互的挑战
智能座舱作为汽车智能化发展的核心,集成了多屏联动和语音交互功能,为驾驶员和乘客提供更便捷的体验。然而,这些功能的测试面临诸多挑战,包括多屏同步性、噪声干扰和复杂场景的处理。本文将详细分析这些挑战,探讨测试方…...
C/C++输入输出(1)
1.getchar和putchar 1.1getchar() 函数原型: 1 int getchar(void); getchar()函数返回用户从键盘输入的字符,使用时不带有任何参数。 程序运行到这个命令就会暂停,等待用户从键盘输入,等同于使用cin或scanf()方法读取一个字符…...
前端面试场景题葵花宝典之四
87.场景面试之大数运算:超过js中number最大值的数怎么处理 在 JavaScript 中,Number.MAX_SAFE_INTEGER(即 2^53 - 1,即 9007199254740991)是能被安全表示的最大整数。超过此值时,普通的 Number 类型会出现…...
探索Elasticsearch:索引的CRUD
在企业环境中,Elasticsearch的索引CRUD(创建Create、读取Read、更新Update、删除Delete)操作是非常基础且频繁使用的功能。这些操作对于管理和维护数据至关重要,尤其是在处理大规模数据集和需要实时搜索与分析的应用场景中。 目录…...
Java数据结构第十六期:走进二叉树的奇妙世界(五)
专栏:Java数据结构秘籍 个人主页:手握风云 目录 一、非递归实现遍历二叉树 1.1. 二叉树的前序遍历 1.2. 二叉树的中序遍历 1.3. 二叉树的后序遍历 一、非递归实现遍历二叉树 1.1. 二叉树的前序遍历 我们这里要使用栈来进行实现。我们反向思考一下为…...
【开源免费】基于SpringBoot+Vue.JS疫情管理系统(JAVA毕业设计)
本文项目编号 T 227 ,文末自助获取源码 \color{red}{T227,文末自助获取源码} T227,文末自助获取源码 目录 一、系统介绍二、数据库设计三、配套教程3.1 启动教程3.2 讲解视频3.3 二次开发教程 四、功能截图五、文案资料5.1 选题背景5.2 国内…...
有关Java中的集合(1):List<T>和Set<T>
学习目标 核心掌握List集合了解Set集合 1.List<T> ● java.util.List。有序列表。 ● List集合元素的特点:有序表示存取有序(因为有索引)而且可以重复 ● List常用实现类: ArrayList、LinkedList、Vector等 1.1 常用方法…...
使用 Spring Boot 实现前后端分离的海康威视 SDK 视频监控
使用 Spring Boot 实现前后端分离的海康威视 SDK 视频监控系统,可以分为以下几个步骤: 1. 系统架构设计 前端:使用 Vue.js、React 或 Angular 等前端框架实现用户界面。后端:使用 Spring Boot 提供 RESTful API,负责与…...
在 Apache Tomcat 中,部署和删除项目
在 Apache Tomcat 中,部署和删除 WAR 文件是常见的操作。以下是详细步骤: 1. 删除 WAR 文件 (1) 停止应用 进入 Tomcat 的管理界面(默认地址:http://localhost:8080/manager/html)。 找到需要删除的应用,…...
宇树科技G1人形机器人:从炫技到实用,AI驱动下的进化跃迁
宇树科技的G1人形机器人近期凭借“720度回旋踢”“走梅花桩”等高难度动作频频出圈,成为人形机器人领域的现象级产品。 G1人形机器人看似炫技的表演背后,实则暗含了技术突破的深意。G1的每一次技能升级,都是对机器人运动控制、平衡算法和A…...
给定计算预算下的最佳LLM模型尺寸与预训练数据量分配
给定计算预算下的最佳LLM模型尺寸与预训练数据量分配 FesianXu 20250304 at Wechat Search Team 前言 如果给定了计算预算 C C C,如何分配LLM的模型尺寸 N N N和训练的数据量 D D D,才能使得模型的效果 L L L最好呢?笔者在此介绍一篇经典的文…...
H5DS编辑器是如何让企业快速构建动态页面
H5DS编辑器核心亮点: 1.拖拽式操作,小白友好:无需设计与代码基础!通过简单拖拽元素、调整文字和动画,即可生成交互式H5页面。内置海量模板和素材库,支持自定义设计风格,轻松适配企业品牌需求。…...
面试题汇总(一)
熙牛医疗面经 1.平衡二叉树的概念 平衡二叉树是一种二叉搜索树,他的左右两个字数的高度差绝对值不超过1,并且左右两个子树都是一颗平衡二叉树,通过左旋,右旋,左右双旋,右左双旋,来保持平衡&…...
论坛系统测试报告
目录 一、项目背景二、论坛系统测试用例思维导图三、论坛系统测试3.1界面测试3.2登陆测试3.3主页测试3.4个人中心测试 四、自动化测试脚本4.1配置驱动4.2创建浏览器类4.3功能测试4.3.1登陆测试4.3.2注册测试4.3.3主页测试4.3.4帖子编辑4.3.5运行主代码 五、BUG分析六、测试总结…...
算法比赛中处理输入和输出
在算法比赛中,不推荐使用 Scanner 和 System.out.println()。Scanner 线程安全,有大量同步操作,读取输入时每次都要解析数据类型,处理大数据量时性能开销大、效率低,易使程序超时间限制。System.out.println() 每次调用…...
llama.cpp: GGUF格式及模型量化参数介绍
GGUF格式介绍 GGUF(GPT-Generated Unified Format)是推理框架llama.cpp 中使用的一种专为大语言模型设计的二进制文件格式,旨在实现模型的快速加载和保存,同时易于读取。GGUF格式的特点: 单文件部署:模型…...
PGlite:浏览器中运行的PostgreSQL
PGlite 是一款基于 WebAssembly(WASM)构建的轻量级 PostgreSQL 数据库引擎,旨在简化开发者在浏览器、Node.js、Bun 或 Deno 环境中运行 PostgreSQL。PGlite 无需复杂的安装或配置,特别适合开发测试、本地化应用及快速原型设计。 一…...
【C++】vector(上):vector的常用接口介绍
文章目录 前言一、vector的介绍二、vector的常用接口介绍1.vector类对象的常见构造2.vector iterator 的使用3.vector类对象的容量操作3.1 size、capacity 和 empty的使用3.2 reserve的使用3.3 resize的使用 4.vector类对象的访问(包含data:返回底层数组…...
【算法】二分查找(上)
目录 一、写好二分查找的四个步骤 二、在排序数组中查找元素的第一个和最后一个位置 三、搜索插入位置 四、x的平方根 通过上篇文章【手撕二分查找】,我们知道了二分查找的【四要素】:初始值、循环条件、mid的计算方式、左右边界更新语句。 循环条件…...
浏览器访问 AWS ECS 上部署的 Docker 容器(监听 80 端口)
✅ 一、ECS 服务配置 Dockerfile 确保监听 80 端口 EXPOSE 80 CMD ["nginx", "-g", "daemon off;"]或 EXPOSE 80 CMD ["python3", "-m", "http.server", "80"]任务定义(Task Definition&…...
RestClient
什么是RestClient RestClient 是 Elasticsearch 官方提供的 Java 低级 REST 客户端,它允许HTTP与Elasticsearch 集群通信,而无需处理 JSON 序列化/反序列化等底层细节。它是 Elasticsearch Java API 客户端的基础。 RestClient 主要特点 轻量级ÿ…...
定时器任务——若依源码分析
分析util包下面的工具类schedule utils: ScheduleUtils 是若依中用于与 Quartz 框架交互的工具类,封装了定时任务的 创建、更新、暂停、删除等核心逻辑。 createScheduleJob createScheduleJob 用于将任务注册到 Quartz,先构建任务的 JobD…...
ESP32 I2S音频总线学习笔记(四): INMP441采集音频并实时播放
简介 前面两期文章我们介绍了I2S的读取和写入,一个是通过INMP441麦克风模块采集音频,一个是通过PCM5102A模块播放音频,那如果我们将两者结合起来,将麦克风采集到的音频通过PCM5102A播放,是不是就可以做一个扩音器了呢…...
鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个医院查看报告小程序
一、开发环境准备 工具安装: 下载安装DevEco Studio 4.0(支持HarmonyOS 5)配置HarmonyOS SDK 5.0确保Node.js版本≥14 项目初始化: ohpm init harmony/hospital-report-app 二、核心功能模块实现 1. 报告列表…...
深度学习习题2
1.如果增加神经网络的宽度,精确度会增加到一个特定阈值后,便开始降低。造成这一现象的可能原因是什么? A、即使增加卷积核的数量,只有少部分的核会被用作预测 B、当卷积核数量增加时,神经网络的预测能力会降低 C、当卷…...
为什么要创建 Vue 实例
核心原因:Vue 需要一个「控制中心」来驱动整个应用 你可以把 Vue 实例想象成你应用的**「大脑」或「引擎」。它负责协调模板、数据、逻辑和行为,将它们变成一个活的、可交互的应用**。没有这个实例,你的代码只是一堆静态的 HTML、JavaScript 变量和函数,无法「活」起来。 …...
华为OD机试-最短木板长度-二分法(A卷,100分)
此题是一个最大化最小值的典型例题, 因为搜索范围是有界的,上界最大木板长度补充的全部木料长度,下界最小木板长度; 即left0,right10^6; 我们可以设置一个候选值x(mid),将木板的长度全部都补充到x,如果成功…...
【读代码】从预训练到后训练:解锁语言模型推理潜能——Xiaomi MiMo项目深度解析
项目开源地址:https://github.com/XiaomiMiMo/MiMo 一、基本介绍 Xiaomi MiMo是小米公司开源的7B参数规模语言模型系列,专为复杂推理任务设计。项目包含基础模型(MiMo-7B-Base)、监督微调模型(MiMo-7B-SFT)和强化学习模型(MiMo-7B-RL)等多个版本。其核心创新在于通过…...
SQL 注入开放与修复
开发: SQL 注入是一种数据库攻击手段。攻击者通过向应用程序提交恶意代码来改变原 SQL 语句的含义, 进而执行任意 SQL 命令,达到入侵数据库乃至操作系统的目的。 例如:下面代码片段中,动态构造并执行了一个 SQ…...
