vue+springboot项目的登录验证码(JAVA自带)

devtools/2024/9/23 14:22:48/

后台springboot

CaptureController

java">package com.example.controller;import com.example.common.Result;
import com.example.service.AuthCodeService;
import com.example.utils.CodeUtils;
import lombok.SneakyThrows;
import org.apache.ibatis.annotations.Param;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.image.BufferedImage;
import java.util.HashMap;
import java.util.Map;@RestController
@RequestMapping("/")
public class CaptureController {@AutowiredAuthCodeService service;/*** 获取验证码文本** @return*/@GetMapping("/getCode")public Result getAuthCode(HttpServletRequest request) {String text = CodeUtils.generateCode();service.bandUserAuthCode(request.getSession().getId(), text);return Result.success(text);}@GetMapping("/getImg")@SneakyThrowspublic ResponseEntity<byte[]> drawAuthCode(@Param("text") String text) {return service.drawAuthCodeImg(text);}@GetMapping("/verifyCode")public Result verifyAuthCode(HttpServletRequest request, @Param("code") String code) {// 获取sessionidString sessionId = request.getSession().getId();boolean isVerificationSuccess = service.authUserCode(sessionId, code);System.out.println("验证结果:" + isVerificationSuccess);if (isVerificationSuccess) { //truereturn Result.success(); // 返回状态码200表示验证成功} else {return Result.error(); // 返回状态码500表示验证失败}}}

 AuthCodeService

java">package com.example.service.impl;import com.example.service.AuthCodeService;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Random;@Service
public class AuthCodeServiceImpl implements AuthCodeService {private String findSession;/*** 绑定用户验证码** @param sessionId sessionId* @param authCode  验证码文本*/@Overridepublic void bandUserAuthCode(String sessionId, String authCode) {authCodeMap.put(sessionId, authCode);findSession = authCodeMap.get(sessionId);}/*** 验证用户验证码** @param sessionId sessionId* @param authCode  验证码文本*/@Overridepublic Boolean authUserCode(String sessionId, String authCode) {System.out.println("authUserCode: " + authCode);
//        String text = authCodeMap.get(sessionId);String text = findSession;System.out.println(authCodeMap.get(sessionId));System.out.println("text: " + text);if (authCode.isEmpty() || !authCode.equals(text)) {//验证码为空或不匹配return false;}// 验证码验证通过,删除验证码authCodeMap.remove(sessionId);return true;}/*** 绘制验证码图片** @param text 文本内容* @return*/@Overridepublic ResponseEntity<byte[]> drawAuthCodeImg(String text) throws IOException {//创建一个115*45的画布BufferedImage canvas = new BufferedImage(115, 45, BufferedImage.TYPE_INT_RGB);//获取画布打画笔对象Graphics g2d = canvas.getGraphics();//创建颜色数组,用于绘制随机颜色ArrayList<Color> colorList = new ArrayList<>();colorList.add(Color.cyan);colorList.add(Color.PINK);colorList.add(Color.ORANGE);colorList.add(Color.green);//创建随机数对象Random rd = new Random();for (int i = 0; i < text.length(); i++) {//获取随机颜色索引int index = rd.nextInt(colorList.size());//设置画笔随机颜色g2d.setColor(colorList.get(index));//设置字体大小g2d.setFont(new Font(null, Font.BOLD, 15));//计算随机x坐标int xPoint = (i + 1) * 20;//计算随机y坐标int yPoint = rd.nextInt(canvas.getHeight() / 2) + 15;g2d.setFont(new Font(null, Font.BOLD, 25));//绘制验证码g2d.drawString(String.valueOf(text.charAt(i)), xPoint, yPoint);//绘制字母g2d.drawString(text.charAt(i) + "", xPoint, yPoint);}//绘制15条干扰线for (int i = 0; i < 15; i++) {g2d.setColor(colorList.get(rd.nextInt(colorList.size())));g2d.drawLine(rd.nextInt(canvas.getWidth()), rd.nextInt(canvas.getHeight()), rd.nextInt(canvas.getWidth()), rd.nextInt(canvas.getHeight()));}//将图片转换为输出流ByteArrayOutputStream baos = new ByteArrayOutputStream();ImageIO.write(canvas, "png", baos);//释放画布资源g2d.dispose();return ResponseEntity.ok().contentType(MediaType.IMAGE_PNG).body(baos.toByteArray());}
}

 AuthCodeService

java">package com.example.service;import com.baomidou.mybatisplus.extension.service.IService;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;import java.io.IOException;
import java.util.HashMap;
import java.util.Map;public interface AuthCodeService {//用于临时存储用户绑定的验证码Map<String, String> authCodeMap = new HashMap<>();/*** 绑定用户验证码* @param sessionId sessionId* @param authCode 验证码文本*/void bandUserAuthCode(String sessionId, String authCode);/*** 验证用户验证码* @param sessionId sessionId* @param authCode 验证码文本*/Boolean authUserCode(String sessionId, String authCode);/*** 绘制验证码图片* @param text 文本内容* @return*/ResponseEntity<byte[]> drawAuthCodeImg(String text) throws IOException;
}

 CodeUtils

java">package com.example.utils;import java.awt.*;
import java.awt.image.BufferedImage;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;public class CodeUtils {/*** 生成4位字符验证码** @return*/public static String generateCode() {//创建字符数组,1-9,A-Z,a-zchar[] arr = {'1', '2', '3', '4', '5', '6', '7', '8', '9', // 数字 1 到 9'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', // 大写字母 A 到 Z'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z' // 小写字母 a 到 z};//创建随机数对象Random rd = new Random();//创建SB对象,用于生成验证码StringBuilder sb = new StringBuilder();//循环四次,拼接四个字符for (int i = 0; i < 4; i++) {//获取随机索引int index = rd.nextInt(arr.length);sb.append(arr[index]);}//返回创建的验证码return sb.toString();}
}

前端Vue

templete模块

<el-form-item prop="captcha"><div style="display: flex; justify-content: center; align-items: center;"><el-input v-model="data.form.captcha" prefix-icon="key" style="margin-right:10px;"placeholder="请输入验证码"></el-input><el-image :src="captchaUrl" @click="fetchCaptchaImage" style="height: 33px; width: 140px;"></el-image></div>
</el-form-item>

js模块

javascript"><script setup>
import {reactive, ref, onMounted} from "vue";
import {ElMessage} from "element-plus";
import router from "../router";
import request from "@/utils/request";const data = reactive({form: {captcha: '',}
});const captchaUrl = ref('');// 获取验证码图片
const fetchCaptchaImage = () => {request.get('http://127.0.0.1:9090/getCode').then(res => {if (res.code === '200') {captchaUrl.value = `http://127.0.0.1:9090/getImg?text=${res.data}`;// 不需要将data.form.captcha设置为空字符串} else {handleCaptchaError('获取验证码图片失败');}}).catch(error => {handleCaptchaError('获取验证码图片时发生网络错误');});
};// 验证验证码
const verifyCaptcha = (captcha) => {return new Promise((resolve, reject) => {if (!captcha) {reject('验证码不能为空');} else {console.log(captcha);request.get(`http://127.0.0.1:9090/verifyCode?code=${captcha}`).then(res => {if (res.code === '200') {ElMessage.success('验证码匹配成功');resolve(); // 验证码匹配成功,执行 resolve 表示验证成功} else {console.log(res.code);console.log(captcha);ElMessage.error('验证码错误,请重新输入');reject('验证码错误'); // 验证码错误,执行 reject 表示验证失败}})}});
};// 刷新验证码
const refreshCaptcha = () => {fetchCaptchaImage();
};const executeLogin = () => {formRef.value.validate((valid) => {if (valid) {request.post('/login', data.form).then(res => {if (res.code === '200') {// 登录成功,保存用户信息到 localStoragelocalStorage.setItem('student-user', JSON.stringify(res.data));ElMessage.success('登录成功');router.push('/home'); // 跳转到主页} else {ElMessage.error(res.msg);}});}});
};const login = async () => {try {await formRef.value.validate(); // 首先验证用户名和密码await verifyCaptcha(data.form.captcha); // 等待验证码验证// 验证码验证成功,执行登录executeLogin();} catch (error) {console.error('登录失败:', error);}
};// 组件加载时刷新验证码
onMounted(refreshCaptcha);</script>


http://www.ppmy.cn/devtools/16633.html

相关文章

浅谈菊风实时音视频 (RTC)与实时操作系统 (RTOS) 在智能硬件领域应用

近年来&#xff0c;菊风通过实时音视频赋能智能手表、智能门禁、智能门锁/门铃、智能眼镜等数十种智能硬件&#xff0c;与一众合作伙伴共同探索在IoT智能硬件领域的不同场景应用&#xff0c;积累了丰富的实践经验。在智能硬件中&#xff0c;RTOS因其轻量化的系统内核&#xff0…

Python 基于 OpenCV 视觉图像处理实战 之 OpenCV 简单人脸检测/识别实战案例 之六 简单进行人脸训练与识别

Python 基于 OpenCV 视觉图像处理实战 之 OpenCV 简单人脸检测/识别实战案例 之六 简单进行人脸训练与识别 目录 Python 基于 OpenCV 视觉图像处理实战 之 OpenCV 简单人脸检测/识别实战案例 之六 简单进行人脸训练与识别 一、简单介绍 二、简单进行人脸训练与识别 1、LBPH…

开源向量数据库比较:Chroma, Milvus, Faiss,Weaviate

语义搜索和检索增强生成(RAG)正在彻底改变我们的在线交互方式。实现这些突破性进展的支柱就是向量数据库。选择正确的向量数据库能是一项艰巨的任务。本文为你提供四个重要的开源向量数据库之间的全面比较&#xff0c;希望你能够选择出最符合自己特定需求的数据库。 什么是向量…

PostgreSQL的学习心得和知识总结(一百三十九)|深入理解PostgreSQL数据库GUC参数 allow_alter_system 的使用和原理

目录结构 注&#xff1a;提前言明 本文借鉴了以下博主、书籍或网站的内容&#xff0c;其列表如下&#xff1a; 1、参考书籍&#xff1a;《PostgreSQL数据库内核分析》 2、参考书籍&#xff1a;《数据库事务处理的艺术&#xff1a;事务管理与并发控制》 3、PostgreSQL数据库仓库…

组合优于继承:什么情况下可以使用继承?

C设计模式专栏&#xff1a;http://t.csdnimg.cn/8Ulj3 目录 1.引言 2.为什么不推荐使用继承 3.相比继承&#xff0c;组合有哪些优势 4.如何决定是使用组合还是使用继承 1.引言 面向对象编程中有一条经典的设计原则:组合优于继承&#xff0c;也常被描述为多用组合&#xff0…

探索AI作画算法的原理:从深度学习到创造性艺术

引言 介绍AI在不同领域的应用&#xff0c;以及AI作画算法对于创造性艺术的影响。概述将在本文中讨论的主要内容。 第一部分&#xff1a;深度学习与计算机视觉 深度学习的基本原理&#xff1a;神经网络的结构和训练过程。计算机视觉的重要性&#xff1a;图像识别、生成和处理…

k8s日常动手实践 ~~ pod访问 pod请求 k8s api ~ 含新版带curl的busybox镜像

前言&#xff1a; 可以使用 Kubernetes API 获取集群信息。使用 Service Account&#xff08;SA&#xff09;进行身份验证&#xff0c;可以以安全的方式访问 Kubernetes API&#xff0c;而无需在 Pod 中使用明文凭据。 以下是一个使用 Service Account 访问 Kubernetes API 获…

Unix 进程基本信息

目录 一、程序执行流程二、进程的执行状态三、进程信息记录3.1 proc结构体3.2 user结构体 四、内存分配4.1 代码段代码段如何管理&#xff1f;4.2 数据段4.3 虚拟地址空间4.4 交换地址APR构成APR数量APR切换 内容来源&#xff1a;《Unix内核源码剖析》 一、程序执行流程 为程序…