SpringBoot + Vue3邮件验证码功能的实现

news2024/12/25 9:15:08

后端

  • SpringBoot
  • maven
  • mysql
  • IDEA

后端负责编写邮件发送的接口逻辑,具体流程如下:

  • 引入相关依赖
  • 配置邮箱信息
  • 编写邮件发送服务接口
  • OK

引入依赖

<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-mail -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-mail</artifactId>
    <version>2.6.7</version>
</dependency>

配置邮箱信息

首先要明白一点,我们实现邮件发送需要一个用来发送邮件到目标用户邮箱里的邮箱,因此,这一步必不可少,也是最主要的一点。关于邮箱配置的具体信息在我的论文一篇文章中已经做过详细的操作说明,为了节省时间,这里就不再拿出来赘述了,建议参考文档CSDN文章 开发必会:SpringBoot邮件集成图文详解

通过你的努力阅读,相信邮箱相关的配置已经做好了,那么现在我们需要将邮箱的信息配置到项目的配置文件application.yml/properties中,参考如下:

  # 配置邮箱
  mail:
    host: smtp.163.com
    username: ilikexff@163.com
    password: 这里放你上面配置好的邮件密码或者授权码
    default-encoding: UTF-8
    protocol: smtp
    port: 465
    properties:
      mail:
        smtp:
          auth: true
          socketFactory:
            class: javax.net.ssl.SSLSocketFactory
            port: 465
          ssl:
            enable: true
          starttls:
            enable: true
            required: true

配置关注做好之后,开始着手开发邮件发送的服务接口;


编写邮件发送服务接口

基本流程:

  1. 编写邮件发送接口;
  2. 编写接口实现
  3. 编写controller层
  4. 接口基本测试
  5. 完成开发

编写服务层的接口,接口代码如下:

/**
 * ===================我亦无它================================
 * project name: big-event
 * author: 八尺妖剑
 * date: 2024/3/31
 * blog: https://www.ilikexff.cn/
 * description 邮件发送接口
 * ====================唯手熟尔===============================
 **/

package cn.ilikexff.service;

import javax.mail.MessagingException;

/**
 * 邮件发送接口
 */
public interface EmailSendService {
    /**
     * 发送普通文本邮件
     * @param to 收件人地址
     * @param subject 邮件主题
     * @param content 邮件内容
     * @param cc 抄送地址
     */
    void sendSimpleMail(String to,String subject,String content,String... cc);

    /**
     * 发送HTML邮件
     * @param to 收件人地址
     * @param subject 邮件主题
     * @param content 邮件内容
     * @param cc 抄送地址
     */
    void sendHtmlMail(String to,String subject,String content,String... cc);

    /**
     * 发送带附件的邮件
     * @param to 收件人
     * @param subject 邮件主题
     * @param content 邮件内容
     * @param filePath 附件地址
     * @param cc 抄送地址
     * @throws MessagingException 邮件发送异常
     */
    void sendAttachmentsMail(String to, String subject, String content, String filePath, String... cc) throws MessagingException;


    /**
     * 发送正文中有静态资源的邮件
     * @param to 收件人地址
     * @param subject 邮件主题
     * @param content 邮件内容
     * @param rscPath 静态资源地址
     * @param rscId 静态资源ID
     * @param cc 抄送地址
     * @throws MessagingException 发送异常
     */
    void sendResourceMail(String to, String subject, String content, String rscPath, String rscId, String... cc) throws MessagingException;


}

关于邮件发送的一些具体信息,如果你看过上面的文章,配合这里每个方法详细的注释,聪明的你应该不用我再过多解释了吧,那么继续实现该接口;

/**
 * ===================我亦无它================================
 * project name: big-event
 * author: 八尺妖剑
 * date: 2024/3/31
 * blog: https://www.ilikexff.cn/
 * description 邮件发送接口的实现
 * ====================唯手熟尔===============================
 **/

package cn.ilikexff.service.impl;

import cn.hutool.core.util.ArrayUtil;
import cn.ilikexff.service.EmailSendService;
import jakarta.mail.MessagingException;
import jakarta.mail.internet.MimeMessage;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.FileSystemResource;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Service;

import java.io.File;

/**
 * 对邮件发送接口的实现
 */

@Service
public class EmailSendServiceImpl implements EmailSendService {
    @Autowired
    private JavaMailSender mailSender;
    @Value("${speing.mail.username}")
    private String from;


    /**
     * 实现普通文本邮件发送
     * @param to 收件人地址
     * @param subject 邮件主题
     * @param content 邮件内容
     * @param cc 抄送地址
     */
    @Override
    public void sendSimpleMail(String to, String subject, String content, String... cc) {
        SimpleMailMessage message = new SimpleMailMessage();
        message.setFrom(from);
        message.setTo(to);
        message.setSubject(subject);
        message.setText(content);
        if(ArrayUtil.isNotEmpty(cc)){
            message.setCc(cc);
        }
        mailSender.send(message);
    }

    /**
     * 实现发送HTML类型邮件
     * @param to 收件人地址
     * @param subject 邮件主题
     * @param content 邮件内容
     * @param cc 抄送地址
     */
    @Override
    public void sendHtmlMail(String to, String subject, String content, String... cc) throws MessagingException {

        MimeMessage message;
        message = mailSender.createMimeMessage();
        MimeMessageHelper helper;
        helper = new MimeMessageHelper(message, true);
        helper.setFrom(from);
        helper.setTo(to);
        helper.setSubject(subject);
        helper.setText(content,true);
        if(ArrayUtil.isNotEmpty(cc)){
            helper.setCc(cc);
        }
        mailSender.send(message);
    }

    /**
     * 实现发送带附件的邮件
     * @param to 收件人
     * @param subject 邮件主题
     * @param content 邮件内容
     * @param filePath 附件地址
     * @param cc 抄送地址
     * @throws MessagingException
     */
    @Override
    public void sendAttachmentsMail(String to, String subject, String content, String filePath, String... cc) throws MessagingException {
        MimeMessage message = mailSender.createMimeMessage();
        MimeMessageHelper helper = new MimeMessageHelper(message, true);
        helper.setFrom(from);
        helper.setTo(to);
        helper.setSubject(subject);
        helper.setText(content);
        if(ArrayUtil.isNotEmpty(cc)){
            helper.setCc(cc);
        }
        FileSystemResource file = new FileSystemResource(new File(filePath));
        String fileName = filePath.substring(filePath.lastIndexOf(File.separator)+1);
        helper.addAttachment(fileName, file);
        mailSender.send(message);
    }

    /**
     * 实现发送正文中有静态资源的邮件
     * @param to 收件人地址
     * @param subject 邮件主题
     * @param content 邮件内容
     * @param rscPath 静态资源地址
     * @param rscId 静态资源ID
     * @param cc 抄送地址
     * @throws MessagingException
     */
    @Override
    public void sendResourceMail(String to, String subject, String content, String rscPath, String rscId, String... cc) throws MessagingException {
        MimeMessage message = mailSender.createMimeMessage();
        MimeMessageHelper helper = new MimeMessageHelper(message, true);
        helper.setFrom(from);
        helper.setTo(to);
        helper.setSubject(subject);
        helper.setText(content, true);
        if (ArrayUtil.isNotEmpty(cc)) {
            helper.setCc(cc);
        }
        FileSystemResource res = new FileSystemResource(new File(rscPath));
        helper.addInline(rscId, res);
        mailSender.send(message);
    }
}

其中,下面的代码是将我们在配置文件中配置好的邮箱的用户名,也就是邮件的发送者注入到该类中,方便后面的方法使用。

@Value("${spring.mail.username}")
private String from;

接下来就是接口的编写了,新建一个controller,内容如下:

    /**
 * Handles the request to send an email verification code.
 * <p>
 * This method generates a random numeric verification code using a utility class,
 * stores the code in Redis with a specified expiration time, and sends the code to the
 * provided email address. The verification code is intended for use in registration or
 * other verification processes.
 * 
 * @param email The target email address to which the verification code will be sent.
 * @return A {@link Result} object containing the generated verification code and a success status.
 */
@GetMapping("/email/code")
public Result sendEmailCode(String email) {
    // 调用工具类生成指定长度的随机验证码
    String code = VerificationUtil.generateNumberCaptcha(6);
    // 将验证码存入redis并指定有效期,单位:秒
    ValueOperations<String, String> operation = stringRedisTemplate.opsForValue();
    operation.set("code",code,30, TimeUnit.SECONDS);
    // 发送验证码
    emailSendService.sendSimpleMail(email,"注册验证码","你的注册验证码为:"+code);
    return Result.success(code,0);
}

由于这里使用了redis保存验证码有效信息,因此需要引入对应的依赖:

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

下面是生成随机验证码的工具类:

/**
 * ===================我亦无它================================
 * project name: big-event
 * author: 八尺妖剑
 * date: 2024/3/31
 * blog: https://www.ilikexff.cn/
 * description 邮件验证码生成工具类
 * ====================唯手熟尔===============================
 **/

package cn.ilikexff.utils;
import java.util.Random;
public class VerificationUtil {
    /**
     * Generates a numeric captcha of a specified length.
     * This method creates a string composed of random digits, where the length of the string
     * is determined by the input parameter.
     * @param length The length of the captcha to generate. Must be a positive integer.
     * @return A string representing the generated numeric captcha.
     */
    public static String generateNumberCaptcha(int length) {
        Random random = new Random();
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < length; i++) {
            sb.append(random.nextInt(10));
        }
        return sb.toString();
    }
}

上面代码中用到的依赖注入:

private final EmailSendService emailSendService;
private final StringRedisTemplate stringRedisTemplate;

/**
 * 使用指定的邮件发送服务和Redis模板构造EmailSendController的实例。
 * 该构造函数允许对EmailSendService和StringRedisTemplate进行依赖注入,
 * 使得控制器能够发送邮件并与Redis进行交互,如存储验证码等操作。
 * @param emailSendService 用于发送邮件的服务。
 * @param stringRedisTemplate 用于字符串操作的Redis模板,此处用于存储验证码。
 */
public EmailSendController(EmailSendService emailSendService, StringRedisTemplate stringRedisTemplate) {
    this.emailSendService = emailSendService;
    this.stringRedisTemplate = stringRedisTemplate;
}

接口测试

测试工具postman

image-20240331124251806

至此,关于邮件验证码的后端部分就先告一段落,接下来使用Vue3写好前端页面,再回过头来进行前后端的联调,确保核心功能正常;


前端

  • Vue3
  • Element-Plus
  • WebStorm
  • JavaScript

编写表单

这个项目本来是没有注册验证码这个需求的,为了更好的演示效果,简单修改了以下原来的表单,修改后的页面如下:

image-20240331163500154

页面有了,接下来就是请求后端的接口,实现点击 获取验证码 按钮发送邮件验证码,为了实现点击之后进入倒计时禁用,这里采用v-if组件来实现,下面是核心代码:

image-20240331163700724


倒计时处理

其中的JavaScript部分如下:

const sms = reactive({
  disabled: false, // 按钮禁用状态
  total: 10, // 倒计时间隔:秒
  count: 0
})
// 邮件验证码,这段你可以忽略,根据自己得项目情况来,这个就是调用后端获取验证码的请求
const sendEmail = async () =>{
  console.log("函数被调用...")
  timerHandler()
  let result =  await sendEmailCodeService(registerData.value.email);
  console.log("邮箱:"+registerData.value.email)
  ElMessage.success("验证码已发送,请注意查收!");
}

// 倒计时实现
const timerHandler = () => {
  sms.count = sms.total
  sms.disabled = true

  let timer = setInterval(() => {
    if (sms.count > 1 && sms.count <= sms.total) {
      sms.count--
    } else {
      sms.disabled = false
      clearInterval(timer)
    }
  }, 1000)
}

差不多就是这样了,当我们点击【获取验证码】之后,该按钮会进入禁用状态并且倒计时提示,效果如下:

image-20240331164130631

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

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

相关文章

论文笔记:GEOLLM: EXTRACTING GEOSPATIALKNOWLEDGE FROM LARGE LANGUAGE MODELS

ICLR 2024 reviewer 评分 35668 1 intro 1.1 地理空间预测 地理空间预测在各个领域都有广泛的应用 包括贫困估算&#xff0c;公共卫生&#xff0c;粮食安全&#xff0c;生物多样性保护&#xff0c;环境保护。。。这些预测中使用的变量包括地理坐标、遥感数据、卫星图像、人类…

手机无线投屏到windows11电脑

1 安装无线投影组件 2 电脑端打开允许其他设备投影的开关 3 手机找到投屏选项 4 手机搜索可用设备连接即可 这里的官方文档给的不太好,给了一些让人眼花撩乱的信息,以下是经过整合的有效信息

PHP在线客服系统源码修复版

源码简介 在线客服系统网站源码https://www.888host.cn/330.html 新增消息预知&#xff0c;消息撤回&#xff0c;消息已读未读&#xff0c; 修复需要刷新才能收到消息 修复客户来源地址 修复消息提示音 修复桌面推送提醒 搭建环境 宝塔面板 &#xff0c;Nginx1.16-1.18 …

【A-012】基于SSH的在线学习考试系统

【A-012】基于SSH的在线学习考试系统 开发环境&#xff1a; Eclipse/MyEclipse、Tomcat8、Jdk1.8 数据库&#xff1a; MySQL 适用于&#xff1a; 课程设计&#xff0c;毕业设计&#xff0c;学习等等 系统介绍 有偿

centos7.5安装gitlab-runner,配置CI/CD流水线

一般不建议gitlab-server和gitlab-runner装在同一台服务器 第一步&#xff1a;安装gitlab-runner,最好和gitlab实例版本一致 # 下载官方gitlab-runner安装脚本 curl -L "https://packages.gitlab.com/install/repositories/runner/gitlab-runner/script.rpm.sh" | s…

基于FreeRTOS系统的STM32简易遥控器设计

项目说明 该项目是一个基于FreeRTOS系统的Stm32遥控器设计。使用该项目主要是自己学习FreeRTOS的使用&#xff0c;以及模块化编程的思想。这个项目应该长期会有更新。 项目开源 github:https://github.com/snqx-lqh/Stm32RemoteControl gitee:https://gitee.com/snqx-lqh/S…

canvas画图,画矩形可拖拽移动,可拖拽更改尺寸大小

提示&#xff1a;canvas画图&#xff0c;画矩形&#xff0c;圆形&#xff0c;直线&#xff0c;曲线可拖拽移动 文章目录 前言一、画矩形&#xff0c;圆形&#xff0c;直线&#xff0c;曲线可拖拽移动总结 前言 一、画矩形&#xff0c;圆形&#xff0c;直线&#xff0c;曲线可拖…

Lucene及概念介绍

Lucene及概念介绍 基础概念倒排索引索引合并分析查询语句的构成 基础概念 Document&#xff1a;我们一次查询或更新的载体&#xff0c;对比于实体类 Field&#xff1a;字段&#xff0c;是key-value格式的数据&#xff0c;对比实体类的字段 Item&#xff1a;一个单词&#xff0…

非周期连续函数的傅里叶变换

首先 我们把一个非周期信号扩展成一个周期信号 然后用傅里叶级数展开 也可以得到对应的级数系数 利用周期趋向于无穷大 可以把傅里叶级数展开就变成了一个积分 而神奇的是积分里其实还有一个积分 这样我们就得到了傅里叶变换对 我们把里面的积分成为函数的傅里叶变换 把外面…

Qt主窗口 之:停靠/悬浮窗口(QDockWidget)

一、QDockWidget概述 QDockWidget 是 Qt 中的一个窗口部件&#xff0c;用于创建可停靠的窗口&#xff0c;通常用于构建多文档接口&#xff08;MDI&#xff09;或可定制的用户界面。QDockWidget 允许用户将窗口停靠在应用程序的主窗口周围&#xff0c;或将其拖动到独立的浮动窗…

【千帆杯】K12教育常规赛 北京场线下交流会心得

千帆杯K12教育常规赛 北京场线下交流会心得 ​ 周日有幸参加了 百度智能云千帆AppBuilder北京场线下交流会 ( 活动链接 )&#xff0c;去线下组队创作了 K12教育 相关的智能体。参赛过程中认识了不少大佬与朋友&#xff0c;抱大佬队友的腿&#xff0c;他的 猜成语 应用获得了线…

Android屏幕硬件宽高和当前View显示区域的宽高,Kotlin

Android屏幕硬件宽高和当前View显示区域的宽高&#xff0c;Kotlin private fun getScreenSize() {if (Build.VERSION.SDK_INT > Build.VERSION_CODES.R) {//屏幕实际显示区域的宽高&#xff0c;包含系Android统的状态栏和导航栏&#xff0c;可以简单理解这就是屏幕硬件尺寸固…

刷题日记——重建二叉树专题

1.层序建树 给定一个二叉树的层序遍历序列&#xff0c;空节点用#表示&#xff0c;例如层序序列&#xff1a;“abc##de#g##f###”&#xff0c;其对应二叉树如下图所示&#xff1a; 分析 创建根节点 TreeNode * rootNULL创建一个队列&#xff0c;用于保存将要插入的位置&#x…

Kubernetes(k8s)架构原理

比如在服务器上部署一个博客应用服务,但是太过受欢迎,访问量太大,应用服务经常会挂,使用自动重启工具,并且将应用服务部署在了好几个服务器上,总算抗住了。后来又上线了商城应用服务和语言应用服务,随着应用服务变多,需求也千奇百怪,有的应用服务不希望被外网访问,有…

CentOS系统下Docker的安装教程

&#x1f31f; 前言 欢迎来到我的技术小宇宙&#xff01;&#x1f30c; 这里不仅是我记录技术点滴的后花园&#xff0c;也是我分享学习心得和项目经验的乐园。&#x1f4da; 无论你是技术小白还是资深大牛&#xff0c;这里总有一些内容能触动你的好奇心。&#x1f50d; &#x…

[Python] 如何导出PDF文件中的图片

文章目录 一、背景说明二、代码编写三、问题3.1、如何得到图片的xref&#xff1f;3.2、xref有什么用呢&#xff1f; 四、总结 一、背景说明 最近在看一份pdf的书籍&#xff0c;其中有一些图片绘制地比较出色&#xff0c;所以就打算将其复制出来&#xff0c;以便于在需要的时候…

webGIS 之 智慧校园案例

1.引入资源创建地图 //index.html <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><meta name"viewport" content&qu…

【PyQt学习篇 · ⑮】:qrc/rcc资源系统

文章目录 qrc使用介绍rcc编译资源rcc 的安装与基本使用 编译成Python文件使用资源系统文件方式一&#xff1a;导入资源系统文件方式二&#xff1a;整合资源系统文件 qrc使用介绍 在PyQt中&#xff0c;qrc文件是一种资源文件&#xff0c;用于将应用程序所需的资源&#xff08;如…

中文Mistral模型介绍(Chinese-Mistral)——中文大语言模型

中文Mistral简介 Chinese-Mistral由清华大学地学系地球空间信息科学实验室开发。 该模型基于Mistral发布的Mistral-7B-v0.1训练得到。首先进行中文词表扩充&#xff0c;然后采用实验室提出的PREPARED训练框架&#xff08;under review&#xff09;在中英双语语料上进行增量预训…

日历插件fullcalendar【笔记】

日历插件fullcalendar【笔记】 前言版权开源推荐日历插件fullcalendar一、下载二、初次使用日历界面示例-添加事件&#xff0c;删除事件 三、汉化四、动态数据五、前后端交互1.环境搭建-前端搭建2.环境搭建-后端搭建3.代码编写-前端代码fullcalendar.htmlfullcalendar.js 4.代码…