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

实现效果

在这里插入图片描述

基本想法就是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("<p style='color: blue'>短信验证码功能测试!,你的验证码为:" + code + "(有效期为一分钟)</p>", 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

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

List item
在这里插入图片描述

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)
}
  • 5
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是使用Spring BootVue.js实现图片验证码登录验证的前后端代码: ## 后端代码(Spring Boot) ### 1. 引入依赖 在`pom.xml`中添加以下依赖: ```xml <dependency> <groupId>com.github.axet</groupId> <artifactId>kaptcha</artifactId> <version>0.0.9</version> </dependency> ``` ### 2. 创建验证码生成器 在`config`包下创建一个`KaptchaConfig`类,用于配置验证码生成器: ```java @Configuration public class KaptchaConfig { @Bean public Producer captchaProducer() { Properties properties = new Properties(); // 配置验证码生成器 // ... return new DefaultKaptcha(); } } ``` ### 3. 创建验证码接口 在`controller`包下创建一个`CaptchaController`类,用于生成验证码图片: ```java @RestController @RequestMapping("/captcha") public class CaptchaController { @Autowired private Producer captchaProducer; @GetMapping("/image") public void captchaImage(HttpServletRequest request, HttpServletResponse response) throws Exception { // 设置响应头信息,告诉浏览器返回的是图片 response.setContentType("image/jpeg"); // 配置验证码生成器 // ... // 生成验证码文本和图片 String captchaText = captchaProducer.createText(); BufferedImage captchaImage = captchaProducer.createImage(captchaText); // 将验证码文本存入session HttpSession session = request.getSession(); session.setAttribute("captchaText", captchaText); // 将验证码图片输出到响应流中 ServletOutputStream out = response.getOutputStream(); ImageIO.write(captchaImage, "jpeg", out); out.flush(); out.close(); } } ``` ### 4. 创建登录接口 在`controller`包下创建一个`LoginController`类,用于处理登录请求: ```java @RestController @RequestMapping("/login") public class LoginController { @PostMapping("/check") public boolean check(@RequestParam String captcha, HttpSession session) { // 获取session中存储的验证码文本 String captchaText = (String) session.getAttribute("captchaText"); // 比较用户输入的验证码和session中存储的验证码是否一致 return captchaText != null && captchaText.equalsIgnoreCase(captcha); } } ``` ## 前端代码(Vue.js) ### 1. 安装依赖 在项目目录下执行以下命令安装依赖: ```bash npm install axios vue-axios vue-qriously ``` ### 2. 创建组件 在`components`目录下创建一个`CaptchaLogin`组件,包含一个输入框、一个验证码图片和一个登录按钮: ```html <template> <div> <input type="text" v-model="captcha" placeholder="请输入验证码" /> <qriously :value="captchaImageUrl"></qriously> <button @click="login">登录</button> </div> </template> <script> import axios from "axios"; import VueAxios from "vue-axios"; import Qriously from "vue-qriously"; export default { name: "CaptchaLogin", components: { Qriously, }, data() { return { captcha: "", captchaImageUrl: "", }; }, created() { this.refreshCaptcha(); }, methods: { refreshCaptcha() { const captchaUrl = `/captcha/image?timestamp=${new Date().getTime()}`; this.captchaImageUrl = captchaUrl; }, login() { axios .post("/login/check", { captcha: this.captcha }) .then((response) => { if (response.data) { alert("登录成功"); } else { alert("验证码错误"); } this.refreshCaptcha(); }); }, }, mounted() { Vue.use(VueAxios, axios); }, }; </script> ``` ### 3. 在页面中使用组件 在需要登录验证的页面中使用`CaptchaLogin`组件: ```html <template> <div> <CaptchaLogin /> </div> </template> <script> import CaptchaLogin from "@/components/CaptchaLogin.vue"; export default { name: "LoginPage", components: { CaptchaLogin, }, }; </script> ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值