当前位置: 首页 > news >正文

登录和注册页面 - 验证码功能的实现

目录

1. 生成验证码

2. 将本地验证码发布成 URL

3. 后端返回验证码的 URL 给前端

4. 前端将用户输入的验证码传给后端

5. 后端验证验证码


1. 生成验证码

使用hutool 工具生成验证码.

1.1 添加 hutool 验证码依赖

<!--  验证码 -->
<dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>5.8.16</version>
</dependency>

1.2 创建验证码的控制器 

@RestController
public class CaptchaController {@Value("${imagepath}")private String imagepath; // 验证码的本地路径@RequestMapping("/getcaptcha")public Object getCaptcha1(){// 1.生成验证码到本地//定义图形验证码的长和宽 (这个验证码的大小需要和自己前端的验证码的大小匹配)LineCaptcha lineCaptcha = CaptchaUtil.createLineCaptcha(128, 50);String uuid = UUID.randomUUID().toString().replace("-","");// 图形验证码写出,可以写出到文件,也可以写出到流lineCaptcha.write(imagepath + uuid + ".png");return AjaxResult.success(imagepath+uuid+".png");}
}

application.propertities 中添加验证码保存路径 (末尾一定要带斜杆)

# 验证码保存路径
imagepath=D:/image/

【注意】

  • 如果项目中配置了拦截器, 那么一定要记得再拦截规则中给验证码的路由放行!!
  • 使用 UUID 每次生成不同地址的验证码

 1.3 前端关键代码

<div class="row" style="margin-bottom: 20px;"><span>验证码</span><input id="checkCode" style="width: 66px;">&nbsp;&nbsp;<img onclick="loadCode()" id="codeimg" src=""style="height: 50px;width: 128px;">
</div>

浏览器直接访问接口 : 127.0.0.1:8080/getcaptcha 

再查看本地路径也确实生成了对应的验证码 : 

 

2. 将本地验证码发布成 URL

2.1 配置映射图片路径

@Configuration
public class AppConfig implements WebMvcConfigurer {@Value("${imagepath}")private String imagepath;/*** 映射图片路径* @param registry*/@Overridepublic void addResourceHandlers(ResourceHandlerRegistry registry) {registry.addResourceHandler("/image/**").addResourceLocations("file:" + imagepath + "/");}
}

使用网络路径 /image/** 映射到本地验证码路径, 注意 "file:" + imagepath + "/"  这最后可能要加上一个斜杆才能生效. (因人而异)

2.2 使用映射后的网络路径访问验证码

浏览器输入: 127.0.0.1:8080/image/b1306474838b4b0e9f8a6ac7606567cb.png

成功访问到了!!

3. 后端返回验证码的 URL 给前端

后端不仅要返回验证码给前端, 还需要返回一个 "验证码的 key" 给前端.

后端返回验证码的 URL 给前端可以理解, 前端需要展示给用户看; 

那么验证码的 key 是啥呢 ???

后端需要将验证码存储 redis, 因为验证码在某一时间内可以生成很多, 而用户输入的正确与否, 需要在后端进行判断, 后端进行判断时, 就得把生成的验证码存储 redis (快), 而存储 redis 我们可以借着前面的 UUID , 把 UUID 作为 key, 验证码作为 value 去存储. 然后再将 key 去传给前端, 前端就可以带着输入的验证码和 key 一起传给后端, 后端就可以拿着 key 去查 redis 得到一个验证码, 然后与前端传过来的作比较即可.

3.1 完善后端 CaptchaController.java 代码

@RestController
public class CaptchaController {@Value("${imagepath}")private String imagepath; // 验证码的本地路径@Resourceprivate RedisTemplate redisTemplate; // 将存储验证码的 key - uuid@RequestMapping("/getcaptcha")public Object getCaptcha(){// 1.生成验证码到本地//定义图形验证码的长和宽 (这个验证码的大小需要和自己前端的验证码的大小匹配)LineCaptcha lineCaptcha = CaptchaUtil.createLineCaptcha(128, 50);String uuid = UUID.randomUUID().toString().replace("-","");// 图形验证码写出,可以写出到文件,也可以写出到流lineCaptcha.write(imagepath+uuid+".png");// 验证码的网络地址String url = "/image/"+uuid+".png";// 将验证码存储到 redisredisTemplate.opsForValue().set(uuid,lineCaptcha.getCode());HashMap<String,String> result = new HashMap<>();result.put("codeurl",url);result.put("codekey",uuid);return AjaxResult.success(result);}
}

4. 前端将用户输入的验证码传给后端

4.1 前端加载验证码

<script>// 验证码keyvar codeKey = "";// 获取并显示验证码function loadCode() {jQuery.ajax({url: "/getcaptcha",type: "GET",data: {},success: function (res) {if (res.code = 200 && res.data != null && res.data != "") {// 获取验证码成功codeKey = res.data.codekey;jQuery("#codeimg").attr("src", res.data.codeurl);}}});}loadCode();
</script>

效果图  

 4.2 前端将验证码和 key 传给后端

jQuery.ajax({url:"/user/reg",type:"post",data:{username:username.val(),password:password.val(),checkCode:checkCode.val(),codeKey:codeKey},success:function(body) {if(body.code==200 && body.data!=null) {alert("恭喜,注册成功!");if(confirm("是否要去登录页面 ?")) {location.href = "login.html";}} else if(body.code == -1) {alert("抱歉, 注册失败, 请重新注册! " + body.msg);} else {alert("该用户名已被使用, 请重新输入!");}}
});

5. 后端验证验证码

5.1 注册功能中验证验证码

@RequestMapping("/reg")
public Object reg(UserInfoVo userInfoVo) {// 1. 非空效验// 省去具体代码....// 2.检查验证码是否正确String redisCodeValue = (String) redisTemplate.opsForValue().get(userInfoVo.getCodeKey());if(!StringUtils.hasLength(redisCodeValue) ||!redisCodeValue.equals(userInfoVo.getCheckCode())) {// 验证码不正确return AjaxResult.fail(-1, "验证码错误!");}// .....// .... 其他业务逻辑return AjaxResult.success(result);
}

登录功能的后端验证验证码其实是一样的方法, 照猫画虎即可~


此处的验证码功能是针对之前的博客 - SSM - 博客系统 来做的一个扩展功能, 有兴趣的可以去实现一下~~

相关文章:

登录和注册页面 - 验证码功能的实现

目录 1. 生成验证码 2. 将本地验证码发布成 URL 3. 后端返回验证码的 URL 给前端 4. 前端将用户输入的验证码传给后端 5. 后端验证验证码 1. 生成验证码 使用hutool 工具生成验证码. 1.1 添加 hutool 验证码依赖 <!-- 验证码 --> <dependency><groupId…...

HDFS的文件块大小(重点)

HDFS 中的文件在物理上是分块存储 &#xff08;Block &#xff09; &#xff0c; 块的大小可以通过配置参数( dfs.blocksize&#xff09;来规定&#xff0c;默认大小在Hadoop2.x/3.x版本中是128M&#xff0c;1.x版本中是64M。 如果一个文件文件小于128M&#xff0c;该文件会占…...

深度学习(二)

目录 一、神经网络 整体架构: 架构细节: 神经元个数的影响: 神经网络过拟合解决: 卷积网络 整体架构: 卷积层 边缘填充 特征尺寸计算 池化层 特征图变化 递归神经网络 一、神经网络 整体架构: 图中分别为输入层、隐层1、隐层2、输出层 通过输入层输入某数值&#xf…...

无涯教程-jQuery - wrapInner( html )方法函数

wrapInner(html)方法使用HTML结构包装每个匹配元素(包括文本节点)的内部子内容。 wrapInner( html ) - 语法 selector.wrapInner( html ) 这是此方法使用的所有参数的描述- html - 将动态创建并环绕目标的HTML字符串。 wrapInner( html ) - 示例 以下是一个简单的示例…...

【unity之IMGUI实践】单例模式管理数据存储【二】

&#x1f468;‍&#x1f4bb;个人主页&#xff1a;元宇宙-秩沅 &#x1f468;‍&#x1f4bb; hallo 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍&#x1f4bb; 本文由 秩沅 原创 &#x1f468;‍&#x1f4bb; 收录于专栏&#xff1a;uni…...

【C++】开源:Linux端ALSA音频处理库

&#x1f60f;★,:.☆(&#xffe3;▽&#xffe3;)/$:.★ &#x1f60f; 这篇文章主要介绍Linux端ALSA音频处理库。 无专精则不能成&#xff0c;无涉猎则不能通。。——梁启超 欢迎来到我的博客&#xff0c;一起学习&#xff0c;共同进步。 喜欢的朋友可以关注一下&#xff0c…...

【Linux | Shell】结构化命令2 - test命令、方括号测试条件、case命令

目录 一、概述二、test 命令2.1 test 命令2.2 方括号测试条件2.3 test 命令和测试条件可以判断的 3 类条件2.3.1 数值比较2.3.2 字符串比较 三、复合条件测试四、if-then 的高级特性五、case 命令 一、概述 上篇文章介绍了 if 语句相关知识。但 if 语句只能执行命令&#xff0c…...

基于单片机的语音识别智能垃圾桶垃圾分类的设计与实现

功能介绍 以51单片机作为主控系统&#xff1b;液晶显示当前信息和状态&#xff1b;通过语音识别模块对当前垃圾种类进行语音识别&#xff1b; 通过蜂鸣器进行声光报警提醒垃圾桶已满&#xff1b;采用舵机控制垃圾桶打开关闭&#xff1b;超声波检测当前垃圾桶满溢程度&#xff1…...

最新版本docker 设置国内镜像源 加速办法

解决问题:加速 docker 设置国内镜像源 目录: 国内加速地址 修改方法 国内加速地址 1.Docker中国区官方镜像 https://registry.docker-cn.com 2.网易 http://hub-mirror.c.163.com 3.ustc https://docker.mirrors.ustc.edu.cn 4.中国科技大学 https://docker.mirrors…...

深度学习——LSTM解决分类问题

RNN基本介绍 概述 循环神经网络&#xff08;Recurrent Neural Network&#xff0c;RNN&#xff09;是一种深度学习模型&#xff0c;主要用于处理序列数据&#xff0c;如文本、语音、时间序列等具有时序关系的数据。 核心思想 RNN的关键思想是引入了循环结构&#xff0c;允许…...

three.js入门二:相机的zoom参数

环境&#xff1a; threejs&#xff1a;129 &#xff08;在浏览器的控制台下输入&#xff1a; window.__THREE__即可查看版本&#xff09;vscodewindowedge 透视相机或正交相机都有一个zoom参数&#xff0c;它可以用来将相机排到的内容在canvas上缩放显示。 注意&#xff1a;…...

sql语法树(select)实例

在SELECT节点下&#xff0c;将"*"&#xff08;表示选择所有列&#xff09;添加为子节点。下面是一个简单的SQL语句示例&#xff1a; SELECT * FROM customers WHERE age > 25 AND city New York;语法树&#xff08;Syntax Tree&#xff09;是由SQL解析器构建的…...

爬虫002_python程序的终端运行_文件运行_ipython的使用---python工作笔记020

用python运行一个文件,就是要写一个.py结尾的文件 然后保存 然后直接cmd中,python 然后写上py文件的路径就可以了 然后看一下内容 看一下终端中运行,直接输入python进入python环境,然后写python代码 回车运行 退出可以用exit()...

智融SW3518S降压协议IC一款适合车充控制芯片

描述 SW3518S 是一款高集成度的多快充协议双口充电芯片&#xff0c; 支持 AC 口任意口快充输出&#xff0c; 支持双口独立限流。 其集成了 5A 高效率同步降压变换器&#xff0c; 支持 PPS/PD/QC/AFC/FCP/SCP/PE/SFCP/VOOC等多种快充协议&#xff0c; 最大输出 PD 100W&#xff…...

虹科活动 | 虹科ADAS自动驾驶研讨会

​​虹科ADAS/自动驾驶研讨会将于8月7日在上海闵行展开——加快ADAS/AD开发步伐&#xff01; 期待您的参与&#xff01;...

LeetCode-每日一题-将数组和减半的最少操作次数

2208. 将数组和减半的最少操作次数 提示 中等 49 相关企业 给你一个正整数数组 nums 。每一次操作中&#xff0c;你可以从 nums 中选择 任意 一个数并将它减小到 恰好 一半。&#xff08;注意&#xff0c;在后续操作中你可以对减半过的数继续执行操作&#xff09; 请你返…...

97、Kafka的性能好在什么地方

Kafka的性能好在什么地方 一、顺序写二、零拷贝三、额外补充 kafka不基于内存&#xff0c;而是硬盘存储&#xff0c;因此消息堆积能力更强 一、顺序写 顺序写 : 利用磁盘的顺序访问速度可以接近内存&#xff0c;kafka的消息都是append操作&#xff0c;partition是有序的&#…...

(2)前端控制器的扩展配置, 视图解析器类型以及MVC执行流程的概述

SpringMVC入门程序的扩展说明 注册前端控制器的细节 在web.xml文件注册SpringMVC的前端控制器DispatcherServlet时使用url-pattern标签中使用/和/*的区别 /可以匹配.html或.js或.css等方式的请求路径,但不匹配*.jsp的请求路径/*可以匹配所有请求(包括.jsp请求), 例如在过滤器…...

GO学习之切片操作

GO系列 1、GO学习之Hello World 2、GO学习之入门语法 3、GO学习之切片操作 4、GO学习之 Map 操作 5、GO学习之 结构体 操作 文章目录 GO系列前言一、什么是切片&#xff08;和数组有什么关系&#xff09;二、切片基本操作2.1 切片定义2.2 添加元素2.3 删除元素2.4 遍历2.5 自定…...

YOLOv8实战口罩佩戴检测(视频教程)

课程链接&#xff1a;https://edu.csdn.net/course/detail/38827 口罩佩戴检测可以应用于公共场所的安全管理、疫情防控监测等多种场景。YOLOv8是前沿的目标检测技术&#xff0c;它基于先前 YOLO 版本在目标检测任务上的成功&#xff0c;进一步提升性能和灵活性。 本课程使用…...

GNN实战:Cora、Citeseer、PubMed三大文献数据集保姆级使用指南(附代码)

GNN实战&#xff1a;Cora、Citeseer、PubMed三大文献数据集深度解析与工程实践 引言&#xff1a;为什么这三个数据集成为GNN研究的"黄金标准"&#xff1f; 在探索图神经网络&#xff08;GNN&#xff09;的浩瀚宇宙中&#xff0c;Cora、Citeseer和PubMed如同三颗璀璨的…...

团队用ai写代码越来越猛但为什么改个功能像在拆炸弹背后是流程断了

最近不少团队反馈&#xff0c;AI Coding 跑得飞快&#xff0c;两周就能堆出新功能&#xff0c;可一旦要改个按钮颜色&#xff0c;整个系统却像在拆炸弹。这种“改功能崩塌”的怪圈&#xff0c;正让许多管理者头疼&#xff1a;明明用了最先进的工具&#xff0c;交付反而更慢了。…...

【STM32-HAL库】火焰传感器实战:从原理到智能火灾预警系统搭建(基于STM32F407ZGT6)

1. 火焰传感器原理与选型指南 火焰传感器作为火灾预警系统的"眼睛"&#xff0c;其核心原理是利用光电效应检测火焰特有的光谱特征。我经手过的工业项目中&#xff0c;90%的火灾误报都源于传感器选型不当。市面上常见的火焰传感器主要分为三类&#xff1a; 红外型&…...

Debian 12上彻底卸载TigerVNC的5个隐藏步骤(附残留文件清理技巧)

Debian 12上彻底卸载TigerVNC的5个隐藏步骤&#xff08;附残留文件清理技巧&#xff09; 作为Linux系统管理员&#xff0c;你是否遇到过TigerVNC卸载后仍然出现端口占用或配置冲突的情况&#xff1f;常规的apt remove往往无法彻底清除所有痕迹。本文将揭示那些鲜为人知的清理技…...

三步修复Windows安全防护:零基础系统工具恢复指南

三步修复Windows安全防护&#xff1a;零基础系统工具恢复指南 【免费下载链接】windows-defender-remover A tool which is uses to remove Windows Defender in Windows 8.x, Windows 10 (every version) and Windows 11. 项目地址: https://gitcode.com/gh_mirrors/wi/wind…...

从移位相加到硬件实现:FPGA二进制乘法器的设计精髓

1. 从纸笔计算到硬件逻辑&#xff1a;二进制乘法的本质 记得第一次学二进制乘法时&#xff0c;我拿着铅笔在纸上画了半天移位相加的步骤。比如计算11011011&#xff0c;就像小学生列竖式一样&#xff0c;先写下110111101&#xff0c;然后11011左移一位变成11010&#xff0c;接着…...

Phi-4-Reasoning-Vision从零开始:双卡4090环境nvidia-smi调优

Phi-4-Reasoning-Vision从零开始&#xff1a;双卡4090环境nvidia-smi调优 1. 项目概述 Phi-4-Reasoning-Vision是基于微软Phi-4-reasoning-vision-15B多模态大模型开发的高性能推理工具&#xff0c;专为双卡4090环境优化。这个工具严格遵循官方SYSTEM PROMPT规范&#xff0c;…...

CSS线性渐变实战:5分钟搞定炫酷按钮背景(附完整代码)

CSS线性渐变实战&#xff1a;5分钟搞定炫酷按钮背景&#xff08;附完整代码&#xff09; 最近在重构一个企业官网时&#xff0c;产品经理突然要求把所有按钮的纯色背景换成"更有设计感"的效果。面对30多个不同尺寸的按钮&#xff0c;手动设计图片背景显然不现实。这时…...

神经网络实战之dsp实现神经网络vad-1

vad神经网络有很多不同的实现&#xff0c;这里的神经网络是基于pytorch实现的&#xff0c;网络结构如下&#xff1a; class MiniVAD(nn.Module):def __init__(self, n_fft512):super().__init__()self.input48 #输入B T 48# 融合层self.fusion nn.Sequential(nn.Linear(self.i…...

解锁毕业论文新姿势:书匠策AI,你的学术超级英雄!

在学术征途上&#xff0c;每一位即将毕业的大学生都怀揣着梦想与挑战&#xff0c;而毕业论文则是那座必须跨越的巍峨大山。面对这座大山&#xff0c;你是否曾感到迷茫、无助&#xff0c;甚至有些力不从心&#xff1f;别怕&#xff0c;今天&#xff0c;就让我带你认识一位学术界…...