spring boot3登录开发-2(3邮件验证码接口实现)

2024-06-06 08:28

本文主要是介绍spring boot3登录开发-2(3邮件验证码接口实现),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

 

⛰️个人主页:     蒾酒

🔥系列专栏:《spring boot实战》


目录

写在前面

上文衔接

接口设计与实现 

1.接口分析

2.实现思路

3.代码实现

1.定义验证码短信HTML模板枚举类

2.定义验证码业务接口

3. 验证码业务接口实现

4.控制层代码

4.测试

写在最后


最近发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。

    点击跳转到学习网站

写在前面

本文介绍了springboot开发后端服务中,邮件验证码接口功能的设计与实现,坚持看完相信对你有帮助。

同时欢迎订阅springboot系列专栏,持续分享spring boot的使用经验。

上文衔接

实现发送验证码邮件接口的前提是项目中已经整合好了邮件服务。上篇文章介绍了springboot整合QQ邮箱SMTP服务:spring boot3整合邮件服务实现邮件发送功能_spring-boot-starter-mail springboot3-CSDN博客icon-default.png?t=N7T8https://blog.csdn.net/qq_62262918/article/details/139244604

接口设计与实现 

1.接口分析

关键点:

  1. 邮件验证码60s发送间隔
  2. 连发多次封禁24H
  3. 5分钟有效期

2.实现思路

接口接收一个邮箱号参数,先去redis查询该邮箱是否有未过期的验证码,如果有先判断发送次数,超过5次,先修改过期时间为24H,再抛发送次数过多异常,少于五次,就再判断发送频率,距离上次发送间隔少于60s,就抛出发送频繁异常,  如果没有未过期的验证码,代表这是第一次发送就直接生成验证码发送短信,接着redis存入一个哈希,key通过手机号生成,value就是,三个键值对,验证码,上次发送时间戳,发送次数(初始为1),默认过期时间5分钟。

  1. 接收手机号参数。
  2. 查询 Redis 中该手机号是否有未过期的验证码。
  3. 如果有未过期的验证码:
    1. 判断发送次数是否超过5次,如果超过5次,修改过期时间为24小时并抛出发送次数过多异常。
    2. 如果发送次数未超过5次,再判断距离上次发送时间间隔是否少于60秒,如果少于60秒,抛出发送频繁异常。
  4. 如果没有未过期的验证码,代表第一次发送:
    1. 生成验证码并发送短信。
    2. 将验证码信息存入 Redis,包括验证码、上次发送时间戳和发送次数(初始为1),设置过期时间为5分钟。

注意事项:

考虑到验证码本身的敏感性,虽然存入Redis是临时的,但考虑安全建议对验证码内容进行加密存储,增强数据的安全性。

考虑对接口调用方进行身份验证,确保只有合法的客户端可以请求发送验证码。

整合redis:

Spring Boot3整合Redis_springboot3整合redis-CSDN博客文章浏览阅读6.6k次,点赞103次,收藏111次。⛰️个人主页: 蒾酒🔥系列专栏:《spring boot实战》目录前置条件1.导依赖2.配置连接信息以及连接池参数3.配置序列化方式4.编写测试已经初始化好一个spring boot项目且版本为3X,项目可正常启动。作者版本为3.2.2初始化教程:新版idea(2023)创建spring boot3项目-CSDN博客https://blog.csdn.net/qq_62262918/article/details/135785412?spm=1001.2014.3001.5501pom.xml:_springboot3整合redishttps://blog.csdn.net/qq_62262918/article/details/136067550?spm=1001.2014.3001.5501

3.代码实现

1.定义验证码短信HTML模板枚举类

在实际业务中可能需要发送各种类型的邮件通知,将不同类型的邮件定义为模板维护在枚举中也是种不错选择。

import lombok.Getter;
import java.util.Locale;/*** @author mijiupro*/
@Getter
public enum EmailTemplateEnum {// 验证码邮件VERIFICATION_CODE_EMAIL_HTML("<html><body>用户你好,你的验证码是:<h1>%s</h1></body></html>","登录验证"),// 用户被封禁邮件通知USER_BANNED_EMAIL("用户你好,你已经被管理员封禁,封禁原因:%s", "封禁通知"),;private final String template;private final String subject;EmailTemplateEnum(String template, String subject) {this.template = template;this.subject = subject;}public String value() {return this.template;}/*** 模板参数填充* @param args 参数集* @return 填充后的字符串*/public String set(Object... args) {return String.format(Locale.ROOT, this.template, args);}
}

2.定义验证码业务接口

public interface CaptchaService {/*** 获取邮箱验证码* @param email 邮箱*/void getMailCaptcha(String email);}

3. 验证码业务接口实现

import com.mijiu.commom.enumerate.EmailTemplateEnum;
import com.mijiu.commom.exception.GeneralBusinessException;
import com.mijiu.api.email.EmailApi;
import com.mijiu.api.sms.SmsApi;
import com.mijiu.service.CaptchaService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import java.util.concurrent.TimeUnit;/*** @author mijiupro*/
@Service
@Slf4j
public class CaptchaServiceImpl implements CaptchaService {private final StringRedisTemplate stringRedisTemplate;private final SmsApi smsUtil;private final EmailApi emailUtil;public CaptchaServiceImpl(StringRedisTemplate stringRedisTemplate, SmsApi smsUtil, EmailApi emailUtil) {this.stringRedisTemplate = stringRedisTemplate;this.smsUtil = smsUtil;this.emailUtil = emailUtil;}@Overridepublic void getMailCaptcha(String email) {getCaptcha("login:email:captcha:" + email);}private void getCaptcha(String hashKey) {BoundHashOperations<String, String, String> hashOps = stringRedisTemplate.boundHashOps(hashKey);// 初始检查String lastSendTimestamp = hashOps.get("lastSendTimestamp");String sendCount = hashOps.get("sendCount");String captcha = hashOps.get("captcha");// 判断发送次数是否超过限制if (StringUtils.isNotBlank(sendCount) && Integer.parseInt(sendCount) >= 5) {hashOps.expire(24, TimeUnit.HOURS); // 重新设置过期时间为24Hthrow new GeneralBusinessException("发送次数过多,请24H后再试");}// 判断发送频率是否过高if (StringUtils.isNotBlank(lastSendTimestamp)) {long lastSendTime = Long.parseLong(lastSendTimestamp);long currentTime = System.currentTimeMillis();long elapsedTime = currentTime - lastSendTime;long interval = 60 * 1000; // 60秒if (elapsedTime < interval) {throw new GeneralBusinessException("发送频繁,请稍后再试");}}// 更新发送次数int newSendCount = StringUtils.isNotBlank(sendCount) ? Integer.parseInt(sendCount) + 1 : 1;// 生成新验证码if (StringUtils.isBlank(captcha)) {captcha = RandomStringUtils.randomNumeric(6);}// 发送邮件或短信sendCaptcha(hashKey, captcha);// 更新 Redis 中的信息hashOps.put("captcha", captcha);hashOps.put("lastSendTimestamp", String.valueOf(System.currentTimeMillis()));hashOps.put("sendCount", String.valueOf(newSendCount));hashOps.expire(5, TimeUnit.MINUTES); // 设置过期时间为5分钟}private void sendCaptcha(String hashKey, String captcha) {// 根据hashKey判断是发送邮件还是短信,然后调用相应的发送方法if("email".equals(hashKey.split(":")[1])){if (!emailUtil.sendHtmlEmail(EmailTemplateEnum.VERIFICATION_CODE_EMAIL_HTML.getSubject(),EmailTemplateEnum.VERIFICATION_CODE_EMAIL_HTML.set(captcha),hashKey.split(":")[3])) {throw new GeneralBusinessException("发送邮件失败");}} else if ( "sms".equals(hashKey.split(":")[1])) {if (!smsUtil.sendSms(hashKey.split(":")[3], captcha)) {throw new GeneralBusinessException("发送短信失败");}}}}

4.控制层代码

import com.mijiu.service.CaptchaService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;/*** @author mijiupro*/
@RestController
@RequestMapping("/captcha")
@Tag(name = "验证码接口", description = "验证码接口相关操作")
public class CaptchaController {private final CaptchaService captchaService;public CaptchaController(CaptchaService captchaService) {this.captchaService = captchaService;}@GetMapping("/mail-captcha/{email}")@Operation(summary = "获取邮箱验证码")public void getEmailCaptcha(@PathVariable String email) {captchaService.getMailCaptcha(email);}}

到这里接口已经实现。

4.测试

用swagger3进行测试:

Spring Boot3整合knife4j(swagger3)_springboot3 knife4j-CSDN博客icon-default.png?t=N7T8https://blog.csdn.net/qq_62262918/article/details/135761392

发送请求

 这是redis已经缓存了验证码信息

 

也收到了验证码邮件

 

写在最后

 邮件验证码接口功能的设计与实现到这里就结束了,任何问题评论区或私信讨论,欢迎指正。

这篇关于spring boot3登录开发-2(3邮件验证码接口实现)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1035583

相关文章

Java图片压缩三种高效压缩方案详细解析

《Java图片压缩三种高效压缩方案详细解析》图片压缩通常涉及减少图片的尺寸缩放、调整图片的质量(针对JPEG、PNG等)、使用特定的算法来减少图片的数据量等,:本文主要介绍Java图片压缩三种高效... 目录一、基于OpenCV的智能尺寸压缩技术亮点:适用场景:二、JPEG质量参数压缩关键技术:压缩效果对比

Java调用C++动态库超详细步骤讲解(附源码)

《Java调用C++动态库超详细步骤讲解(附源码)》C语言因其高效和接近硬件的特性,时常会被用在性能要求较高或者需要直接操作硬件的场合,:本文主要介绍Java调用C++动态库的相关资料,文中通过代... 目录一、直接调用C++库第一步:动态库生成(vs2017+qt5.12.10)第二步:Java调用C++

Redis分片集群的实现

《Redis分片集群的实现》Redis分片集群是一种将Redis数据库分散到多个节点上的方式,以提供更高的性能和可伸缩性,本文主要介绍了Redis分片集群的实现,具有一定的参考价值,感兴趣的可以了解一... 目录1. Redis Cluster的核心概念哈希槽(Hash Slots)主从复制与故障转移2.

springboot+dubbo实现时间轮算法

《springboot+dubbo实现时间轮算法》时间轮是一种高效利用线程资源进行批量化调度的算法,本文主要介绍了springboot+dubbo实现时间轮算法,文中通过示例代码介绍的非常详细,对大家... 目录前言一、参数说明二、具体实现1、HashedwheelTimer2、createWheel3、n

使用Python实现一键隐藏屏幕并锁定输入

《使用Python实现一键隐藏屏幕并锁定输入》本文主要介绍了使用Python编写一个一键隐藏屏幕并锁定输入的黑科技程序,能够在指定热键触发后立即遮挡屏幕,并禁止一切键盘鼠标输入,这样就再也不用担心自己... 目录1. 概述2. 功能亮点3.代码实现4.使用方法5. 展示效果6. 代码优化与拓展7. 总结1.

Mybatis 传参与排序模糊查询功能实现

《Mybatis传参与排序模糊查询功能实现》:本文主要介绍Mybatis传参与排序模糊查询功能实现,本文通过实例代码给大家介绍的非常详细,感兴趣的朋友跟随小编一起看看吧... 目录一、#{ }和${ }传参的区别二、排序三、like查询四、数据库连接池五、mysql 开发企业规范一、#{ }和${ }传参的

使用Python开发一个简单的本地图片服务器

《使用Python开发一个简单的本地图片服务器》本文介绍了如何结合wxPython构建的图形用户界面GUI和Python内建的Web服务器功能,在本地网络中搭建一个私人的,即开即用的网页相册,文中的示... 目录项目目标核心技术栈代码深度解析完整代码工作流程主要功能与优势潜在改进与思考运行结果总结你是否曾经

Docker镜像修改hosts及dockerfile修改hosts文件的实现方式

《Docker镜像修改hosts及dockerfile修改hosts文件的实现方式》:本文主要介绍Docker镜像修改hosts及dockerfile修改hosts文件的实现方式,具有很好的参考价... 目录docker镜像修改hosts及dockerfile修改hosts文件准备 dockerfile 文

Java利用docx4j+Freemarker生成word文档

《Java利用docx4j+Freemarker生成word文档》这篇文章主要为大家详细介绍了Java如何利用docx4j+Freemarker生成word文档,文中的示例代码讲解详细,感兴趣的小伙伴... 目录技术方案maven依赖创建模板文件实现代码技术方案Java 1.8 + docx4j + Fr

SpringBoot首笔交易慢问题排查与优化方案

《SpringBoot首笔交易慢问题排查与优化方案》在我们的微服务项目中,遇到这样的问题:应用启动后,第一笔交易响应耗时高达4、5秒,而后续请求均能在毫秒级完成,这不仅触发监控告警,也极大影响了用户体... 目录问题背景排查步骤1. 日志分析2. 性能工具定位优化方案:提前预热各种资源1. Flowable