SpringBoot实现图形验证码
目录
项目创建
前端代码实现
约定前后端交互接口
需求分析
接口定义
Hutool工具
实现服务器端代码
引入依赖
获取验证码
验证码校验
调整前端代码
随着安全性的要求越来越高,目前许多项目中都使用了验证码,验证码也有各种类型,如 图形验证码、短信验证码、邮件验证码、人脸识别等,这些不同类型的验证码可以根据实际需求和安全性要求进行选择和应用,保护网站和用户免受恶意攻击
在本篇文章中,我们来学习图形验证码的实现
验证码的实现方式有很多,可以由前端实现,也可以由后端进行实现,也有很多的插件和工具包可以使用,在这里,我们使用 Hutool 提供的小工具实现
验证码需要实现功能:
1. 页面生成验证码,点击图片可进行刷新
2. 输入验证码,点击提交,验证用户输入验证码是否正确,正确则进行页面跳转
项目创建
我们首先创建项目,并引入相关依赖

前端代码实现
接下来,我们实现两个简单的前端界面:
1. 验证码界面
2. 验证成功后跳转的界面

index.html
<!DOCTYPE html>
<html lang="en"><head><meta charset="utf-8"><title>验证码</title><style>#inputCaptcha {height: 30px;vertical-align: middle; }#verificationCodeImg{vertical-align: middle; }#checkCaptcha{height: 40px;width: 100px;}</style>
</head><body><h1>输入验证码</h1><div id="confirm"><input type="text" name="inputCaptcha" id="inputCaptcha"><img id="verificationCodeImg" src="/captcha/getCaptcha" style="cursor: pointer;" title="看不清?换一张" /><input type="button" value="提交" id="checkCaptcha"></div><script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.4/jquery.min.js"></script><script>$("#verificationCodeImg").click(function(){$(this).hide().attr('src', '/captcha/getCaptcha?dt=' + new Date().getTime()).fadeIn();});$("#checkCaptcha").click(function () {alert("判断验证码是否正确");});</script>
</body></html>
success.html
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>验证成功</title>
</head>
<body><h1>验证成功</h1>
</body>
</html>
约定前后端交互接口
需求分析
后端需要提供两个服务:
1. 生成验证码,并返回
2. 校验验证码是否正确
接口定义
1. 生成验证码
[URL]
GET /captcha/getCaptcha
[请求参数]
[响应]
{
验证码图片内容}
2. 校验验证码是否正确
[URL]
POST /captcha/check
[请求参数]
captcha=xmad
[响应]
{
true}
根据用户输入的验证码,校验验证码是否正确,校验成功,返回true;校验失败,返回false
Hutool工具
我们使用 Hutool 提供的小工具来实现验证码
Hutool是一个Java工具包类库,对文件、流、加密解密、转码、正则、线程、XML等JDK方法进行封装,组成各种Util工具类
Hutool是一个小而全的Java工具类库,通过静态方法的封装,降低相关API学习成本,提高效率

Hutool官网:https://hutool.cn
实现服务器端代码
引入依赖
<dependency><groupId>cn.hutool</groupId><artifactId>hutool-captcha</artifactId><version>5.8.26</version></dependency>
由于我们只需要实现验证码相关功能,因此只需要引入验证码部分依赖
获取验证码

我们可以通过提供的指南来学习如何使用
其中提供了:线段干扰验证码、圆圈干扰验证码、扭曲干扰验证码以及自定义验证码
我们通过其提供的例子来学习:

我们在 test 中 学习验证码的生成:
@SpringBootTest
class CaptchaControllerTest {@Testvoid getCaptcha() {//定义图形验证码的长和宽LineCaptcha lineCaptcha = CaptchaUtil.createLineCaptcha(200, 100);//图形验证码写出,可以写出到文件,也可以写出到流lineCaptcha.write("d:/line.png");//输出codeSystem.out.println("生成验证码:" + lineCaptcha.getCode());}
}
运行,观察结果:

且在D盘下成功生成验证码:

同样的,我们可以生成圆圈干扰验证码、扭曲干扰验证码等,大家可自行进行实现
接下来,我们实现验证码的生成
在实现验证码时,需要指定图片的长、宽和验证码的过期时间(也可指定验证码字符个数、干扰元素个数等),我们在 Constants 中进行定义
public class Constants {public static final Integer CAPTCHA_WIDTH = 100;public static final Integer CAPTCHA_HEIGHT = 40;public static final long EXPIRATION_TIME = 60 * 1000;
}
由于当用户输入验证码时,我们需要进行校验,因此,我们需要对生成的验证码进行存储,同时,需要存储验证码的生成时间,以便判断验证码是否超时
public class Constants {public static final Integer CAPTCHA_WIDTH = 100;public static final Integer CAPTCHA_HEIGHT = 40;public static final long EXPIRATION_TIME = 60 * 1000;public static final String CAPTCHA_KEY = "captcha";public static final String CAPTCHA_DATE = "date";
}
接下来我们来实现 CaptchaController
@RequestMapping("/captcha")
@RestController
@Slf4j
public class CaptchaController {/*** 生成验证码* @param session* @param response*/@GetMapping("/getCaptcha")public void getCaptcha(HttpSession session, HttpServletResponse response) {// 定义图形验证码的长和宽LineCaptcha lineCaptcha = CaptchaUtil.createLineCaptcha(Constants.CAPTCHA_WIDTH, Constants.CAPTCHA_HEIGHT);// 设置返回数据类型response.setContentType("image/jpeg");// 禁止使用缓存response.setHeader("Pragma", "No-cache");try {// 输出到页面lineCaptcha.write(response.getOutputStream());// 将 生成的验证码 和 验证码生成时间 存储到session中session.setAttribute(Constants.CAPTCHA_KEY, lineCaptcha.getCode());session.setAttribute(Constants.CAPTCHA_DATE, new Date());// 关闭流response.getOutputStream().close();} catch (IOException e) {throw new RuntimeException(e);}}
}
运行程序,此时成功生成验证码

验证码校验
/*** 验证码校验* @param captcha* @param session* @return*/@PostMapping("/check")public boolean checkCaptcha(String captcha, HttpSession session) {log.info("接收到验证码: {}", captcha);// 参数校验if(!StringUtils.hasLength(captcha)) {return false;}// 获取存储的验证码和生成时间String code = (String) session.getAttribute(Constants.CAPTCHA_KEY);Date createTime = (Date) session.getAttribute(Constants.CAPTCHA_DATE);// 判断验证码是否正确(验证码一般忽略大小写)if(captcha.equalsIgnoreCase(code)) {// 判断验证码是否过时if(createTime == null || System.currentTimeMillis() - createTime.getTime() < Constants.EXPIRATION_TIME) {return true;}return false;}return false;}
将用户输入的验证码与存储在 session 中的验证码进行对比,判断其是否相同,若相同且在1min内,则验证成功
在这里,我们就不对其进行测试了,在调整前端代码后,一起进行测试
调整前端代码
接下来,我们修改 index.html
<script>$("#verificationCodeImg").click(function(){$(this).hide().attr('src', '/captcha/getCaptcha?dt=' + new Date().getTime()).fadeIn();});$("#checkCaptcha").click(function () {$.ajax({url: "/captcha/check",type: "post",data: {captcha: $("#inputCaptcha").val()},success: function(result) {if(result) {location.href = "success.html";}else {alert("验证码错误或已超时");}}})});</script>
再次运行程序,此时输入验证码进行验证:

验证成功:

验证失败:

相关文章:
SpringBoot实现图形验证码
目录 项目创建 前端代码实现 约定前后端交互接口 需求分析 接口定义 Hutool工具 实现服务器端代码 引入依赖 获取验证码 验证码校验 调整前端代码 随着安全性的要求越来越高,目前许多项目中都使用了验证码,验证码也有各种类型,如 …...
【JVM基础01】——介绍-初识JVM运行流程
目录 1- 引言:初识JVM1-1 JVM是什么?(What)1-1-1 概念1-1-2 优点 1-2 为什么学习JVM?(Why) 2- 核心:JVM工作的原理(How)⭐2-1 JVM 的组成部分及工作流程2-2 学习侧重点 3- 小结(知识点大纲):3-1 JVM 组成3…...
图数据库 - Neo4j简介
深入理解 Neo4j 与 Cypher 语法 什么是 Neo4j Neo4j 是一个基于图的数据库管理系统,它使用图形理论来表示数据关系。这种数据库与传统的关系型数据库不同,它更适合处理高度互联的数据结构。 基本概念 图:在 Neo4j 中,数据以图的…...
C#环境与数据类型
文章目录 C#环境.NET 框架集成开发环境 创建一个C#项目数据类型值类型引用类型对象类型object动态类型dynamic字符串类型string 指针类型 类型转换隐式转换显示转换(强制转换)C#提供的类型转换方法Convert类Parse方法TryParse方法 C#环境 .NET 框架 C#是…...
jenkins系列-06.harbor
https://github.com/goharbor/harbor/releases?page2 https://github.com/goharbor/harbor/releases/download/v2.3.4/harbor-offline-installer-v2.3.4.tgz harbor官网:https://goharbor.io/ 点击 Download now 链接,会自动跳转到上述github页面&am…...
kotlin get set
在 Kotlin 中,如果想实现一个类的属性可以从外部读取但不能修改,可以使用自定义的 getter 和 private setter。以下是一个示例代码: class MyClass {var myProperty: Stringprivate set // 使 setter 私有化,外部无法修改get // …...
Flask包算法服务
常规包算法服务,就是比较简单,直接起一个fastapi就可以了。 import time import asyncio from aidraw import engineer_log as eng from fastapi import FastAPI from pydantic import BaseModel from typing import Optional from aidraw.ardraw import run_aidraw_api# 起…...
Flowable(一个开源的工作流和业务流程管理引擎)中与事件相关的一些核心概念
Flowable(一个开源的工作流和业务流程管理引擎)中与事件相关的一些核心概念 Flowable(一个开源的工作流和业务流程管理引擎)中与事件相关的一些核心概念,包括它们的作用和触发场景。以下是对这些内容的简要说明&#x…...
深度解析:景区客服系统如何助力旅游业可持续发展
一、引言 在全球化与信息化交织的时代背景下,旅游业正以前所未有的速度发展,成为推动经济增长、文化交流与环境保护的重要力量。景区作为旅游业的核心组成部分,其服务质量和管理水平直接影响到游客的满意度和行业的可持续发展。景区客服系统…...
风险评估:IIS的安全配置,IIS安全基线检查加固
「作者简介」:冬奥会网络安全中国代表队,CSDN Top100,就职奇安信多年,以实战工作为基础著作 《网络安全自学教程》,适合基础薄弱的同学系统化的学习网络安全,用最短的时间掌握最核心的技术。 这一章节我们需…...
uniapp 截取两条数据 进行页面翻页滚动
// 轮播信息 <view class"sales_list" ><view class"sales_item" v-for"(item,index) in sellDisplayList" :key"index" click"salesFn(item)"><image :src"item.goodsImg"></image><…...
python笔记(转存ipynb)------1
list1 ["tom","cat","Lili"] print(list1[0].title())Tom#append()列表方法在列表末尾添加新元素 list1.append(233) print(list1) #可以先创建空列表,再进行追加append(..)以添加[tom, cat, Lili, 233]#insert()列表方法插入元素 l…...
excel系列(二) - 利用 easypoi 快速实现 excel 文件导入导出
一、介绍 在上篇文章中,我们介绍了 apache poi 工具实现 excel 文件的导入导出。 本篇我们继续深入介绍另一款优秀的 excel 工具库:easypoi。 二、easypoi 以前的以前,有个大佬程序员,跳到一家公司之后就和业务人员聊上了&…...
邀请函|2024第八届中国太阳能电池浆料与金属化技术展
2024第八届中国国际太阳能电池浆料与金属化技术展览会 地点:深圳国际会展中心 时间:2025年06-月25日-27日 地点:上海新国际博览中心 时间:2024年12月18日-20日 主办单位:上海氟伦展览有限公司 指导单位:中国新材料技术协会 中国电子学会 耐…...
图像边缘检测:技术原理与算法解析
图像边缘检测是计算机视觉和图像处理中的一个核心任务,它旨在识别图像中亮度变化明显的点,从而识别出图像的边缘。边缘是图像中的重要特征,对于后续的图像分析、物体识别和图像分割等任务具有至关重要的作用。本文将深入探讨图像边缘检测的技…...
【Python星启航】少儿编程精英启蒙之旅 - 大纲
1. 计算机基础与编程环境 计算机的基本构成 编程语言与编程环境介绍 Python语言的特点与优势 安装与配置Python环境 2. 计算机历史与发展 计算机的起源与早期发展 个人电脑的普及与影响 当代计算机技术的前沿动态 计算机在未来教育中的角色 3. 编程基础概念 变量的定义与作…...
MATLAB的mat文件转换成json文件
内参矩阵 (K):相机的内在参数矩阵,通常是一个3x3的矩阵,包含了相机的焦距(fxfx和fyfy)和主点(光学中心)的坐标(cxcx和cycy)。这个矩阵将图像坐标转换为归一化相机…...
STM32第九课:STM32-基于标准库的42步进电机的简单I/O控制(附电机教程,看到即赚到)
一:步进电机简介 步进电机又称为脉冲电机,简而言之,就是一步一步前进的电机。基于最基本的电磁铁原理,它是一种可以自由回转的电磁铁,其动作原理是依靠气隙磁导的变化来产生电磁转矩,步进电机的角位移量与输入的脉冲个数严格成正比…...
文件安全传输系统,如何保障信创环境下数据的安全传输?
文件安全传输系统是一套旨在保护数据在传输过程中的安全性和完整性的技术或解决方案。通常包括以下几个关键组件: 加密:使用强加密算法来确保文件在传输过程中不被未授权访问。 身份验证:确保只有授权用户才能访问或传输文件。 完整性校验…...
论文分享|AAAI2024‘北航|用大语言模型缩小有监督和无监督句子表示学习的差距
先说结论,大语言模型除了作为聊天的Agent,也可以为检索模型生成优质的文本对训练数据,从而做到无监督场景下也能够适用。这里分享一篇AAAI2024的工作,重点探讨如何生成比评估集更困难的训练数据来提升无监督句子表示学习质量&…...
变量 varablie 声明- Rust 变量 let mut 声明与 C/C++ 变量声明对比分析
一、变量声明设计:let 与 mut 的哲学解析 Rust 采用 let 声明变量并通过 mut 显式标记可变性,这种设计体现了语言的核心哲学。以下是深度解析: 1.1 设计理念剖析 安全优先原则:默认不可变强制开发者明确声明意图 let x 5; …...
解决Ubuntu22.04 VMware失败的问题 ubuntu入门之二十八
现象1 打开VMware失败 Ubuntu升级之后打开VMware上报需要安装vmmon和vmnet,点击确认后如下提示 最终上报fail 解决方法 内核升级导致,需要在新内核下重新下载编译安装 查看版本 $ vmware -v VMware Workstation 17.5.1 build-23298084$ lsb_release…...
UDP(Echoserver)
网络命令 Ping 命令 检测网络是否连通 使用方法: ping -c 次数 网址ping -c 3 www.baidu.comnetstat 命令 netstat 是一个用来查看网络状态的重要工具. 语法:netstat [选项] 功能:查看网络状态 常用选项: n 拒绝显示别名&#…...
最新SpringBoot+SpringCloud+Nacos微服务框架分享
文章目录 前言一、服务规划二、架构核心1.cloud的pom2.gateway的异常handler3.gateway的filter4、admin的pom5、admin的登录核心 三、code-helper分享总结 前言 最近有个活蛮赶的,根据Excel列的需求预估的工时直接打骨折,不要问我为什么,主要…...
第25节 Node.js 断言测试
Node.js的assert模块主要用于编写程序的单元测试时使用,通过断言可以提早发现和排查出错误。 稳定性: 5 - 锁定 这个模块可用于应用的单元测试,通过 require(assert) 可以使用这个模块。 assert.fail(actual, expected, message, operator) 使用参数…...
大模型多显卡多服务器并行计算方法与实践指南
一、分布式训练概述 大规模语言模型的训练通常需要分布式计算技术,以解决单机资源不足的问题。分布式训练主要分为两种模式: 数据并行:将数据分片到不同设备,每个设备拥有完整的模型副本 模型并行:将模型分割到不同设备,每个设备处理部分模型计算 现代大模型训练通常结合…...
Web 架构之 CDN 加速原理与落地实践
文章目录 一、思维导图二、正文内容(一)CDN 基础概念1. 定义2. 组成部分 (二)CDN 加速原理1. 请求路由2. 内容缓存3. 内容更新 (三)CDN 落地实践1. 选择 CDN 服务商2. 配置 CDN3. 集成到 Web 架构 …...
OPENCV形态学基础之二腐蚀
一.腐蚀的原理 (图1) 数学表达式:dst(x,y) erode(src(x,y)) min(x,y)src(xx,yy) 腐蚀也是图像形态学的基本功能之一,腐蚀跟膨胀属于反向操作,膨胀是把图像图像变大,而腐蚀就是把图像变小。腐蚀后的图像变小变暗淡。 腐蚀…...
招商蛇口 | 执笔CID,启幕低密生活新境
作为中国城市生长的力量,招商蛇口以“美好生活承载者”为使命,深耕全球111座城市,以央企担当匠造时代理想人居。从深圳湾的开拓基因到西安高新CID的战略落子,招商蛇口始终与城市发展同频共振,以建筑诠释对土地与生活的…...
C#中的CLR属性、依赖属性与附加属性
CLR属性的主要特征 封装性: 隐藏字段的实现细节 提供对字段的受控访问 访问控制: 可单独设置get/set访问器的可见性 可创建只读或只写属性 计算属性: 可以在getter中执行计算逻辑 不需要直接对应一个字段 验证逻辑: 可以…...
