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的计算方式、左右边界更新语句。 循环条件…...
能耗监控系统:OpenClaw+nanobot自动记录电脑用电数据并生成报告
能耗监控系统:OpenClawnanobot自动记录电脑用电数据并生成报告 1. 为什么需要自动化能耗监控 去年夏天,我的电费账单突然比平时高了30%。作为程序员,我第一反应是排查电脑设备的用电情况。但手动记录USB电表数据实在太麻烦——需要定时查看…...
聊聊 COMSOL 激光热应力模型那些事儿
Comsol激光热应力模型以及步骤讲解视频(8分钟) 我是高价买来的 卖出去回回血 只卖模型不 COMSOL激光热应力模型,采用固体力学、固体传热研究激光焊接下材料的应力及温度变化情况,研究指定点的温度、应力随时间的变化情况。最近我入手了一个超棒的 COMSO…...
Open SWE 协作层:GitHub 深度集成与人在回路(HITL)设计
Open SWE 协作层:GitHub 深度集成与人在回路(HITL)设计Open SWE 不是一个孤立的系统,它的真正力量来自于与现有开发工作流的深度整合。从 GitHub Issue 触发任务到自动创建 Pull Request,从计划审批到执行干预——「人…...
STM32CubeMX + HAL 库:定时器输入捕获的进阶应用,多通道PWM信号同步测量与动态分析
1. 多通道PWM信号同步测量的核心挑战 在电机控制或无人机舵机系统中,经常需要同时监测多个PWM信号的实时状态。比如四轴飞行器的四个电调信号,或者机械臂的六个关节舵机反馈。传统单通道测量方法需要轮流采样,无法捕捉各通道间的相位关系&…...
HTML表单回车键的隐藏陷阱:为什么你的input总在刷新页面?5种解决方案实测
HTML表单回车键的隐藏陷阱与实战解决方案 你是否曾在电商后台系统填写冗长的商品信息时,习惯性按下回车键换行,却发现整个页面突然刷新,刚刚输入的数据全部消失?这种令人抓狂的体验背后,隐藏着HTML表单设计中的一个经典…...
Sora死了
好莱坞杀死了 Sora:传统行业在 AI 浪潮下的无谓挣扎摘要:2026 年 3 月 24 日,OpenAI 宣布关闭 Sora,距离正式发布仅 6 个月。表面看是迪士尼退出授权协议导致的商业失败,实质是传统内容行业对 AI 技术抵制的缩影。本文…...
OpenCore Legacy Patcher:老旧Mac硬件适配与系统兼容完整指南
OpenCore Legacy Patcher:老旧Mac硬件适配与系统兼容完整指南 【免费下载链接】OpenCore-Legacy-Patcher 体验与之前一样的macOS 项目地址: https://gitcode.com/GitHub_Trending/op/OpenCore-Legacy-Patcher 你是否还在为2012年之前的Mac无法升级到最新macO…...
认知雷达前沿技术 从认知到量子:雷达技术的跨范式融合
目录 二、知识图谱解析 关键概念关联说明 三、章节结构层级 四、概念关联与技术成熟度分析 五、核心学术观点提炼 六、关键术语中英对照表 本章探讨了认知雷达(Cognitive Radar)与量子雷达(Quantum Radar)的融合路径,构建了一个从生物启发到量子极限的雷达技术演进框架。…...
C#实战:5分钟搞定Winform鼠标坐标实时追踪(附API对比)
C#实战:Winform鼠标坐标追踪的深度优化与API选择指南 在自动化测试工具开发或屏幕绘图软件构建过程中,精确获取鼠标坐标是基础却关键的功能需求。许多开发者往往只满足于实现基本功能,却忽略了不同API选择对性能、精度和系统兼容性的深远影响…...
【事务】Spring Framework核心——事务管理:ACID特性、隔离级别、传播行为、@Transactional底层原理、失效场景
文章目录事务管理一、事务核心基石:ACID四大特性二、事务并发问题与隔离级别2.1 并发事务引发的3大核心读异常2.2 SQL标准4大隔离级别2.3 核心补充:MVCC与隔离级别的关联三、Spring事务传播行为3.1 第一类:支持当前事务(优先加入已…...
