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

后台springboot

CaptureController

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

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

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

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模块

<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.mzph.cn/bicheng/3445.shtml

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

相关文章

Java openrasp记录-01

例子1 https://github.com/anbai-inc/javaweb-expression 一个hook ognl、spel、MVEL表达式注入的例子 用的是asm5进行字节码修改 采用premain进行插桩&#xff0c;重写transform方法 expClassList是要hook的类&#xff0c;这里定义在MethodHookDesc 这里判断hook点通过类名…

Java并发编程:ThreadPoolExecutor详细源码解析与应用

Thread直接创建线程的弊端 在开始解析ThreadPoolExecutor类之前&#xff0c;让我们先来了解直接创建线程所带来的弊端。在Java中&#xff0c;线程是资源密集型对象&#xff0c;每当需要并发执行任务时&#xff0c;直接创建新线程会带来以下问题&#xff1a; 资源消耗 每个线…

贪吃蛇身子改进加贪吃蛇向右移动

1. 蛇移动的思想&#xff1a; 其实就是删除头节点 &#xff0c;增加尾节点&#xff1b;一句代码搞定 struct Snake *p; p head; head head -> next; free(p) 防止造成多的空间节点 2.增加尾节点代码思想&#xff1a; 2.1 .开辟new 节点的空间 struct Snake *new (stru…

解决Android studio更换sdk地址后flutter项目显示no device selected

问题描述 因为之前sdk的路径在c盘上&#xff0c;经常在更新或下在sdk后c盘饱满&#xff0c;于是就更换了sdk的路径&#xff0c;更换sdk路径后就导致flutter项目在选择设备的时候出现no device selected 找不到设备&#xff0c;但是在device Manager可以看到物理设备或者是虚拟…

Java设计模式:使用责任链模式和状态模式优化‘审批流程‘

Java设计模式&#xff1a;使用责任链模式和状态模式优化审批流程 摘要引言 需求流程图正文内容&#x1f4d0; 基本概念介绍 功能实现示例1:设计模式&#xff1a;责任链模式方法&#xff1a;好处&#xff1a; 示例2:设计模式&#xff1a;责任链模式方法和操作流程&#xff1a;好…

【canvas】前端创造的图片粒子动画效果:HTML5 Canvas 技术详解

前端创造的图片粒子动画效果&#xff1a;HTML5 Canvas 技术详解 我们将深入探讨如何通过 HTML5 的 Canvas 功能&#xff0c;将上传的图片转换成引人入胜的粒子动画效果。这种效果将图片分解成小粒子&#xff0c;并在用户与它们交互时产生动态变化。我们将分步骤详细解析代码&a…

EasyRecovery数据恢复软件2025永久免费电脑版下载

EasyRecovery数据恢复软件是一款业界知名的数据恢复工具&#xff0c;它凭借强大的恢复能力和广泛的数据兼容性&#xff0c;帮助用户从各种存储设备中恢复丢失或删除的数据。以下是关于EasyRecovery数据恢复软件的详细介绍。 EasyRecovery绿色破解下载网盘链接: https://pan.ba…

自动驾驶行业源代码防泄漏解决方案

行业背景&#xff1a; 随着新一代信息通信及人工智能技术的快速发展&#xff0c;汽车作为这些新技术应用的重要载体&#xff0c;正在加速向智能化和网联化转型&#xff0c;以自动驾驶研发为主业的企业也越来越多&#xff0c;如何保障自己研发的算法、模型、系统不被研发人员离…

Linux入门攻坚——20、systemd、(sysvinit、upstart重温)

再一次讲到Linux系统启动流程&#xff1a; POST --> Boot Sequence --> Bootloader(grub) --> kernel initramfs(initrd) --> rootfs --> /sbin/init 对于init&#xff0c;即系统内核加载完毕后&#xff08;加载kernel和切换根文件系统&#xff09;运行…

STM32H750外设ADC之开始和结束数据转换功能

目录 概述 1 开始转换 1.1 使能ADSTART 1.2 使能JADSTART 1.3 ADSTART 通过硬件清零 2 转换时序 3 停止正在进行的转换&#xff08; ADSTP、 JADSTP&#xff09; 3.1 停止转换功能实现 3.2 停止转换流程图 概述 本文主要讲述了STM32H750外设ADC之开始和结束数据转换…

CentOS8/RHEL8 root密码破解

我们知道root是CentOS8/RHEL8系统的管理员用户&#xff0c;一般情况下&#xff0c;我们是不会把其密码忘记的&#xff0c;如果万一忘记了&#xff0c;如果破解root密码呢&#xff0c;今天就为大家详细讲讲。 1.CentOS8/RHEL8 root密码破解 1.默认安装及默认配置情况下&#x…

实践遥感场景目标检测,基于YOLOv8全系列【n/s/m/l/x】参数模型开发构建遥感场景下MSTAR数据基础上的目标检测识别系统

遥感相关的实践在我们前面的系列博文中也有相关的一些实践&#xff0c;基于MASTAR数据集开发构建对应的目标检测系统在前文也有一些介绍&#xff0c;感兴趣的话可以自行移步阅读即可&#xff1a; 《基于YOLOv7开发构建MSTAR雷达影像目标检测系统》 《基于yolov5n的轻量级MSTA…

前端开发攻略---用原生JS在网页中也能实现语音识别

1、语音识别的过程 语音识别涉及三个过程&#xff1a;首先&#xff0c;需要设备的麦克风接收这段语音&#xff1b;其次&#xff0c;语音识别服务器会根据一系列语法 (基本上&#xff0c;语法是你希望在具体的应用中能够识别出来的词汇) 来检查这段语音&#xff1b;最后&#xf…

Git操作与异常处理

文章目录 常用操作1、代码拉取2、代码提交3、暂存区状态4、提交代码5、推送远程仓库 异常处理【1】报错信息&#xff1a;Cannot pull into a repository with state: MERGING【2】报错信息&#xff1a;You have not concluded your merge (MERGE_HEAD exists)【3】报错信息&…

【网络编程】网络编程概念 | TCP和UDP的区别 | UDP数据报套接字编程 | Socket

文章目录 网络编程一、什么是网络编程1.TCP和UDP的区别 二、UDP数据报套接字编程DatagramSocketDatagramPacket回显服务器&#xff08;echo server&#xff09; 网络编程 一、什么是网络编程 通过网络&#xff0c;让两个主机之间能够进行通信。基于通信来完成一定的功能。 ​…

2.7设计模式——Proxy 代理模式(结构型)

意图 为其它对象提供一种代理以控制这个对象的访问。 结构 Proxy保存一个引用使得代理可以访问实体&#xff1b;提供一个与Subject的接口相同的接口&#xff0c;使代理可以用来替代实体&#xff1b;控制实体的存取&#xff0c;并可能负责创建和删除它&#xff1b;其他功能依赖…

[实验]Keil 4下仿真三星2440A芯片的汇编及CPIO控制实验

一、安装Keil uVision4 (详细安装过程忽略) 点击finish完成安装 二、新建项目&#xff0c;导入项目文件 选择对应的芯片&#xff0c;此处我们选择三星的S3C2440A&#xff0c;点击OK 在Source Group 1处右键&#xff0c;点击Add Files to "Sourcce Group 1’…将下图…

Linux之ebpf(1)基础使用

Linux之ebpf(1)基础使用 Author: Once Day Date: 2024年4月20日 一位热衷于Linux学习和开发的菜鸟&#xff0c;试图谱写一场冒险之旅&#xff0c;也许终点只是一场白日梦… 漫漫长路&#xff0c;有人对你微笑过嘛… 全系列文章可以参考专栏&#xff1a;Linux基础知识_Once-D…

非对称渐开线齿轮学习笔记分享

最近有小伙伴遇到了非对称渐开线齿轮的加工问题,花了些时间学习了解一下,下面是总结的学习笔记,有兴趣的朋友可以瞅瞅: 目录: 为什么要采用非对称? 非对称有什么优点? 非对称齿形如何加工? 非对称齿轮怎么测量? 非对称齿轮建模 为什么要采用非对称? 现在的传动要求…

关于浏览器360导航无法更改

当前环境场景&#xff1a; 浏览器&#xff1a;Microsoft Edge 版本 121.0.2277.106 (正式版本) (64 位) 系统&#xff1a;Windows 11 家庭中文版 23H2 问题描述 首先出现这种情况会让我们非常的气愤但是又束手无策&#xff0c;看到这个页面简直就恨的牙根痒痒&#xff0c;但是…