用vue和Springboot实现一个短信验证码发送验证功能

实现效果

用vue和Springboot实现一个短信验证码发送验证功能_第1张图片

基本想法就是1、后端发送邮箱验证码。2、用户输入验证码,后端在进行验证码校验。
其他该有的邮件校验参数等方法就自行考虑清楚,本文主要记录两个主要功能如何实现。

后端使用的工具类

1、邮件发送MailUtil

package com.lcc.myblog.utils;

import jakarta.annotation.Resource;
import jakarta.mail.MessagingException;
import jakarta.mail.internet.MimeMessage;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.mail.javamail.JavaMailSenderImpl;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Component;

import java.time.Duration;

@Component
public class MailUtil {
    @Resource
    private JavaMailSenderImpl mailSender;
    @Autowired
    private RedisTemplate<String,String> redisTemplate;
    public boolean mail(String email) throws MessagingException {
        MimeMessage mimeMessage = mailSender.createMimeMessage();
        //生成随机验证码
        String code = CodeGeneratorUtil.generateCode(6);
        System.out.println("用户:"+email+" 生成的验证码是:"+code);
        MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true);
        //设置一个html邮件信息
        helper.setText("

短信验证码功能测试!,你的验证码为:" + code + "(有效期为一分钟)

"
, true); //设置邮件主题名 helper.setSubject("LCC----发来了验证码"); //发给谁-》邮箱地址 helper.setTo(email); //谁发的-》发送人邮箱 helper.setFrom("你自己的qq邮箱"); redisTemplate.opsForValue().set(email, code, Duration.ofMinutes(1)); mailSender.send(mimeMessage); return true; } }

2、CodeGeneratorUtil验证码生成工具类

package com.lcc.myblog.utils;

import java.util.UUID;

public class CodeGeneratorUtil {
    /**
     * 生成指定长度的验证码
     *
     * @param length 长度
     * @return
     */
    public static String generateCode(int length) {
        return UUID.randomUUID().toString().substring(0, length);
    }

     /**
     * 雪花算法生成用户注册
     */
    public static long snowflake() {
        SnowUtil idutil = new SnowUtil();
        return idutil.nextId();
    }
}

后端需要的pom文件依赖和所需application.yml配置文件

    <!-- 邮箱验证码       -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-mail</artifactId>
        </dependency>
  mail:
    # 发送者邮箱
    username: ""
    #申请到的授权码
    password: ""
    # 配置 SMTP 服务器地址
    host: smtp.qq.com
    # 端口号465587
    port: 465
    protocol: smtps
    # 默认的邮件编码为UTF-8
    default-encoding: UTF-8
    # 配置SSL 加密工厂
    properties:
      mail:
        smtp:
          socketFactoryClass: javax.net.ssl.SSLSocketFactory
          #表示开启 DEBUG 模式,这样,邮件发送过程的日志会在控制台打印出来,方便排查错误
          debug: true
          ssl: true

这里需要申请授权码,要去邮箱里去设置,流程如下:

用vue和Springboot实现一个短信验证码发送验证功能_第2张图片
用vue和Springboot实现一个短信验证码发送验证功能_第3张图片

controller层

创建一个EmailController,里面设置两个方法,一个是发送邮件,一个是验证。
注意这里需要redis缓存验证码过期时间,因为验证码属于一个经常变化的信息。

package com.lcc.myblog.controller;

import com.lcc.myblog.pojo.Result;
import com.lcc.myblog.utils.MailUtil;
import com.lcc.myblog.utils.ThreadLocalUtil;
import jakarta.mail.MessagingException;
import jakarta.validation.constraints.Email;
import jakarta.validation.constraints.Pattern;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.util.StringUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.Map;

@RestController
@Validated
public class EmailController {
    @Autowired
    private MailUtil mailUtil;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    //   发送验证码
    @PostMapping("/emailCode")
    public Result emailCode(@Email String email) throws MessagingException {
        ValueOperations<String, String> stringStringValueOperations = stringRedisTemplate.opsForValue();
        String code = stringStringValueOperations.get(email);
        //若redis存在
        if (!StringUtils.isEmpty(code)){
            return Result.error(email+": +" + code + "已存在,还未过期");
        }
        if (mailUtil.mail(email)){
            return Result.success();
        }
        return Result.error("邮箱发送失败");
    }
    //验证验证码
    @PostMapping("/code")
    public Result<String> SureCode(@Pattern(regexp ="^.\\S{5,6}" )String code,@Email String email ){
        //打印
        System.out.println("新邮箱: "+email+" ,用户填写的验证码是: "+code);
        //从redis里拿出code
        ValueOperations<String, String> stringStringValueOperations = stringRedisTemplate.opsForValue();
        String OriCode = stringStringValueOperations.get(email);
        System.out.println("新邮箱: "+email+" ,后端生成的验证码是: "+OriCode);
        if (StringUtils.isEmpty(OriCode)){
            return Result.error( "验证码已失效,请重新发送!");
        }
        if (code.equals(OriCode)){
            System.out.println("比较正确");
            System.out.println(Result.success(email));
            return Result.success(email);
        }
        return Result.error("验证码不正确!");
    }
}

前端VUE部分

1、页面表单

                <el-form :model="userInfo" :rules="rules" label-width="100px" size="large">
                    <el-form-item label="登录名称">
                        <el-input v-model="userInfo.username" disabled></el-input>
                    </el-form-item>
                    <el-form-item label="性别生日">
                        <el-col :span="8">
                            <el-select v-model="userInfo.sex" placeholder="请选择你的性别">
                                <el-option label="男" value="男" />
                                <el-option label="女" value="女" />
                            </el-select>
                        </el-col>
                        <el-col style="margin-left: 20px;" :span="12">
                            <el-date-picker label="生日" v-model="userInfo.birthday" type="date" placeholder="生日"
                                style="width: 100%" />
                        </el-col>
                    </el-form-item>
                    <el-form-item label="用户昵称" prop="nickname">
                        <el-span span="8">
                            <el-input  v-model="userInfo.nickname"></el-input>
                        </el-span>
                    </el-form-item>
                    <el-form-item label="用户邮箱" prop="email">
                        <el-col span="12">
                            <el-input :disabled="flag" v-model="userInfo.email"></el-input>
                        </el-col>
                        <el-col style="margin-left: 25px;" span="12">
                            <el-link v-if="flag" type="primary" size="large" @click="clickemaliupdate">点击修改</el-link>
                            <el-link v-else type="danger" size="large" @click="cancleEmail">取消修改</el-link>
                        </el-col>
                    </el-form-item>
                    <el-form-item v-show="!flag" label="邮箱验证码" prop="code">
                        <el-input style="width: 150px; margin-right: 20px;" placeholder="邮箱验证码" v-model="userInfo.code"></el-input>
                        <el-button type="primary" v-if="flag2" @click="clickEmail">发送验证码</el-button>
                        <el-button type="success" v-else @click="clickSureCode" >确认验证码</el-button>
                    </el-form-item>
                    <el-form-item>
                        <el-button type="primary" @click="updateUserInfo">保存修改</el-button>
                    </el-form-item>
                </el-form>

2、页面js

import { userMailService } from '@/api/user.js'
// 2 发送邮箱验证码
const SendMail = async()=>{
    if(originEmail.value === userInfo.value.email){
        ElMessage.error("邮箱未更改,无需发送");
        flag2.value=true
    }else{
        let resultMail =await userMailService(userInfo.value)
        console.log("这个东西是"+resultMail.code)
        if(resultMail.code===0){
            ElMessage.success("发送成功")
            flag2.value=false
        }
        if(resultMail.code===1){
            ElMessage.error(resultMail.value.message)
        }
        
    }
}

// 1 点击发送邮件
const clickEmail = ()=>{
    SendMail()    
}
// 点击修改邮箱
const clickemaliupdate = ()=>{
    flag.value = false
    flag2.value=true
}
// 取消修改邮件
const cancleEmail=()=>{
    flag.value = true
    flag2.value=false
    // 还原邮箱值
    userInfo.value.email = originEmail.value
}

import { UserSureCodeService } from '@/api/user.js'
// 确认验证码
const clickSureCode=async()=>{
    let reslut = await UserSureCodeService(userInfo.value)
    console.log("异步后"+reslut.data)
    if(reslut.code === 0){
        ElMessage.success("邮箱验证成功")
        originEmail.value=reslut.data
        // 更改修改状态
        cancleEmail()
    }else{
        ElMessage.error(reslut.value.message)
    }

}

3、页面路径访问

// 发送邮件,生成验证码
export const userMailService = (userInfo)=>{
    let params = new URLSearchParams();
    params.append('email',userInfo.email)
    return request.post('/emailCode',params) 
}

//验证验证码code
export const UserSureCodeService=(userInfo)=>{
    let params = new URLSearchParams();
    params.append('code',userInfo.code)
    params.append('email',userInfo.email)
    return request.post("/code",params)
}

你可能感兴趣的:(个人项目开发杂记,vue.js,spring,boot,前端)