验证码案例
目录
前言
一、Hutool工具介绍
1.1 Maven
1.2 介绍
1.3 实现类
二、验证码案例
2.1 需求
2.2 约定前后端交互接口
2.2.1 需求分析
2.2.2 接口定义
2.3 后端生成验证码
2.4 前端接收验证码图片
2.5 后端校验验证码
2.6 前端校验验证码
2.7 后端完整代码
前言
验证码实现方式很多,可以前端实现,也可以后端实现,网上也有比较多的插件或者工具包可以使用,咱们选择使用Hutool提供的小工具来实现。
一、Hutool工具介绍
Hutool是一个Java工具包类库,对文件、流、加密解密、转码、正则、线程、XML等JDK方法进行封装,组成各种Util工具类。Hutool官网:https://hutool.cn/
1.1 Maven
如果你想在项目中使用Hutool中的某个模块,在项目的pom.xml的dependencies中加入以下内容:
<dependency><groupId>cn.hutool</groupId><artifactId>hutool-captcha</artifactId><version>5.8.22</version>
</dependency>
1.2 介绍
验证码功能位于cn.hutool.captcha包中,核心接口为ICaptcha,此接口定义了以下方法:
createCode创建验证码,实现类需同时生成随机验证码字符串和验证码图片getCode获取验证码的文字内容verify验证验证码是否正确,建议忽略大小写write将验证码图片写出到目标流中
其中write方法只有一个OutputStream,ICaptcha实现类可以根据这个方法封装写出到文件等方法。
AbstractCaptcha为一个ICaptcha抽象实现类,此类实现了验证码文本生成、非大小写敏感的验证、写出到流和文件等方法,通过继承此抽象类只需实现createImage方法定义图形生成规则即可。
1.3 实现类
LineCaptcha线段干扰的验证码
贴栗子:
import cn.hutool.captcha.CaptchaUtil;
import cn.hutool.captcha.LineCaptcha;
import cn.hutool.core.lang.Console;public class LineCaptchaTest {public static void main(String[] args) {//定义图形验证码的长和宽LineCaptcha lineCaptcha = CaptchaUtil.createLineCaptcha(200, 100);//图形验证码写出,可以写出到文件,也可以写出到流lineCaptcha.write("d:/line.png");//输出codeConsole.log(lineCaptcha.getCode());//验证图形验证码的有效性,返回boolean值lineCaptcha.verify("1234");//重新生成验证码lineCaptcha.createCode();lineCaptcha.write("d:/line.png");//新的验证码Console.log(lineCaptcha.getCode());//验证图形验证码的有效性,返回boolean值lineCaptcha.verify("1234");}
}
控制台截图生成的验证码:
在写入的路径中查看代码生成的验证码截图:

CircleCaptcha 圆圈干扰验证码
import cn.hutool.captcha.CaptchaUtil;
import cn.hutool.captcha.CircleCaptcha;
import cn.hutool.core.lang.Console;public class CircleCaptchaTest {public static void main(String[] args) {//定义图形验证码的长、宽、验证码字符数、干扰元素个数CircleCaptcha captcha = CaptchaUtil.createCircleCaptcha(200, 100, 4, 20);//CircleCaptcha captcha = new CircleCaptcha(200, 100, 4, 20);//图形验证码写出,可以写出到文件,也可以写出到流captcha.write("d:/circle.png");//输出codeConsole.log(captcha.getCode());//验证图形验证码的有效性,返回boolean值captcha.verify("1234");}
}
控制台截图生成的验证码:

在写入的路径中查看代码生成的验证码截图:

ShearCaptcha 扭曲干扰验证码
import cn.hutool.captcha.CaptchaUtil;
import cn.hutool.captcha.ShearCaptcha;
import cn.hutool.core.lang.Console;public class ShearCaptchaTest {public static void main(String[] args) {//定义图形验证码的长、宽、验证码字符数、干扰线宽度ShearCaptcha captcha = CaptchaUtil.createShearCaptcha(200, 100, 4, 4);//ShearCaptcha captcha = new ShearCaptcha(200, 100, 4, 4);//图形验证码写出,可以写出到文件,也可以写出到流captcha.write("d:/shear.png");//输出codeConsole.log(captcha.getCode());//验证图形验证码的有效性,返回boolean值captcha.verify("1234");}
}
控制台截图生成的验证码:

在写入的路径中查看代码生成的验证码截图:

二、验证码案例
2.1 需求
需求如下:
- 页面生成验证码
- 输入验证码,点击提交,验证用户输入验证码是否正确,正确则进行页面跳转
2.2 约定前后端交互接口
2.2.1 需求分析
后端需要提供两个服务:
- 生成验证码,并返回验证码
- 校验验证码是否正确
2.2.2 接口定义
1、生成验证码:
url:/captcha/get
param:无
return:图片的内容
2、校验验证码
url:/captcha/check
param:inputCode
return:true/false
2.3 后端生成验证码
import cn.hutool.captcha.CaptchaUtil;
import cn.hutool.captcha.LineCaptcha;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import java.io.IOException;@RestController
@RequestMapping("/captcha")
public class CaptchaController {@RequestMapping("/get")public void getCaptcha(HttpServletResponse response) {//定义图形验证码的长和宽LineCaptcha lineCaptcha = CaptchaUtil.createLineCaptcha(200, 100);//图像验证码写出,可以写出到文件,也可以写出到流,此处写出到流try {lineCaptcha.write(response.getOutputStream());} catch (IOException e) {throw new RuntimeException(e);}}
}
小技巧:在我们每写完一个后端代码模块时,我们可以进行测试,看是否有错误,避免后续代码量过多发生错误时不知道哪块出错。
根据后端定义的url进行测试截图:

2.4 前端接收验证码图片
<!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/get" 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/get?dt=' + new Date().getTime()).fadeIn();});$("#checkCaptcha").click(function () {alert("验证码校验");});</script>
</body></html>
验证前端是否有问题:

2.5 后端校验验证码
import cn.hutool.captcha.CaptchaUtil;
import cn.hutool.captcha.LineCaptcha;
import com.example.demo.model.CaptchaProperties;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import java.io.IOException;
import java.util.Date;@RestController
@RequestMapping("/captcha")
public class CaptchaController {private final static long session_valid_timeout = 60 * 1000;@Autowiredprivate CaptchaProperties captchaProperties;@RequestMapping("/check")public Boolean check(HttpSession session, String inputCode) {//验证码输入的内容和用户输入的进行比较//从session获取信息if (!StringUtils.hasLength(inputCode)) {return false;}String savedCode = (String) session.getAttribute(captchaProperties.getSession().getKey());Date saveDate = (Date) session.getAttribute(captchaProperties.getSession().getDate());if (inputCode.equalsIgnoreCase(savedCode)) {//判断验证码是否过期if (saveDate != null && System.currentTimeMillis() - saveDate.getTime() < session_valid_timeout) {return true;}return true;}return false;}
}
检查校验验证码是否存在问题:
1、先查看后端生成的验证码

2、根据校验验证的url进行验证
首先先输入错误的验证码观察返回ture或者false,如果返回false证明验证码输入错误或者过期,否则反正true。
先输入错误的验证码1234截图:
再输入正确的验证码截图:

2.6 前端校验验证码
<!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/get" 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/get?dt=' + new Date().getTime()).fadeIn();});$("#checkCaptcha").click(function () {$.ajax({url: "/captcha/check",type: "post",data: {inputCode: $("#inputCaptcha").val()},success: function(result) {if (result) {location.href = "success.html";} else {alert("验证码错误或者过期");}}})});</script>
</body></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>
运行截图:
2.7 后端完整代码
package com.example.demo.controller;import cn.hutool.captcha.CaptchaUtil;
import cn.hutool.captcha.LineCaptcha;
import com.example.demo.model.CaptchaProperties;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import java.io.IOException;
import java.util.Date;@RestController
@RequestMapping("/captcha")
public class CaptchaController {private final static long session_valid_timeout = 60 * 1000;@Autowiredprivate CaptchaProperties captchaProperties;@RequestMapping("/get")public void getCaptcha(HttpSession session, HttpServletResponse response) {//定义图形验证码的长和宽LineCaptcha lineCaptcha = CaptchaUtil.createLineCaptcha(captchaProperties.getWidth(), captchaProperties.getHeight());//设置缓存类型response.setContentType("image/jpeg");//禁止缓存response.setHeader("Progma", "No-cache");//图像验证码写出,可以写出到文件,也可以写出到流,此处写出到流try {lineCaptcha.write(response.getOutputStream());//存储sessionsession.setAttribute(captchaProperties.getSession().getKey(), lineCaptcha.getCode());session.setAttribute(captchaProperties.getSession().getDate(), new Date());} catch (IOException e) {throw new RuntimeException(e);}}@RequestMapping("/check")public Boolean check(HttpSession session, String inputCode) {//验证码输入的内容和用户输入的进行比较//从session获取信息if (!StringUtils.hasLength(inputCode)) {return false;}String savedCode = (String) session.getAttribute(captchaProperties.getSession().getKey());Date saveDate = (Date) session.getAttribute(captchaProperties.getSession().getDate());if (inputCode.equalsIgnoreCase(savedCode)) {//判断验证码是否过期if (saveDate != null && System.currentTimeMillis() - saveDate.getTime() < session_valid_timeout) {return true;}}return false;}
}
配置文件:
captcha:width: 200height: 100session:key: captcha_session_keydate: captcha_session_date
captcha配置:
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;@Component
@ConfigurationProperties(prefix = "captcha")
@Data
public class CaptchaProperties {private Integer width;private Integer height;private Session session;@Datapublic static class Session {private String key;private String date;}
}
相关文章:
验证码案例
目录 前言 一、Hutool工具介绍 1.1 Maven 1.2 介绍 1.3 实现类 二、验证码案例 2.1 需求 2.2 约定前后端交互接口 2.2.1 需求分析 2.2.2 接口定义 2.3 后端生成验证码 2.4 前端接收验证码图片 2.5 后端校验验证码 2.6 前端校验验证码 2.7 后端完整代码 前言…...
python身份证ocr接口功能免费体验、身份证实名认证接口
翔云人工智能API开放平台提供身份证实名认证接口、身份证识别接口,两者的相结合可以实现身份证的快速、精准核验,当用户在进行身份证实名认证操作时,仅需上传身份证照片,证件识别接口即可快速、精准的对证件上的文字信息进行快速提…...
屏幕空间反射技术在AI绘画中的作用
在数字艺术和游戏开发的世界中,真实感渲染一直是追求的圣杯。屏幕空间反射(Screen Space Reflection,SSR)技术作为一种先进的图形处理手段,它通过在屏幕空间内模拟光线的反射来增强场景的真实感和视觉冲击力。随着人工…...
JDK下载安装Java SDK
Android中国开发者官网 Android官网 (VPN翻墙) 通过brew命令 下载OracleJDK(推荐) 手动下载OracleJDK(不推荐) oracle OracleJDK下载页 查找硬件设备是否已存在JDK环境 oracle官网 备注: JetPack JavaDevelopmentKit Java开发的系统SDK OpenJDK 开源免费SDK …...
【ARM Cache 系列文章 1.2 -- Data Cache 和 Unified Cache 的详细介绍】
请阅读【ARM Cache 及 MMU/MPU 系列文章专栏导读】 及【嵌入式开发学习必备专栏】 文章目录 Data Cache and Unified Cache数据缓存 (Data Cache)统一缓存 (Unified Cache)数据缓存与统一缓存的比较小结 Data Cache and Unified Cache 在 ARM架构中,缓存(…...
Debian13将正式切换到基于内存的临时文件系统
以前的内存很小,旅行者一号上的计算机内存只有68KB,现在的内存可以几十G,上百G足够把系统全部装载在内存里运行,获得优异的性能和极速响应体验。 很多小型系统能做到这一点,Linux没有那么激进,不过Debian …...
设计模式-工厂方法(创建型)
创建型-工厂方法 简单工厂 将被创建的对象称为“产品”,将生产“产品”对象称为“工厂”;如果创建的产品不多,且不需要生产新的产品,那么只需要一个工厂就可以,这种模式叫做“简单工厂”,它不属于23中设计…...
分布式事务大揭秘:使用MQ实现最终一致性
本文作者:小米,一个热爱技术分享的29岁程序员。如果你喜欢我的文章,欢迎关注我的微信公众号“软件求生”,获取更多技术干货! 大家好,我是小米,一个热爱分享技术的29岁程序员,今天我们来聊聊分布式事务中的一种经典实现方式——MQ最终一致性。这是一个在互联网公司中广…...
【IoT NTN】3GPP R18中关于各类IoT设备在NTN中的增强和扩展
博主未授权任何人或组织机构转载博主任何原创文章,感谢各位对原创的支持! 博主链接 本人就职于国际知名终端厂商,负责modem芯片研发。 在5G早期负责终端数据业务层、核心网相关的开发工作,目前牵头6G技术研究。 博客内容主要围绕…...
vs - vs2015编译gtest-v1.12.1
文章目录 vs - vs2015编译gtest-v1.12.1概述点评笔记将工程迁出到本地后,如果已经编译过工程,将工程Revert, Clean up 干净。编译用的CMake, 优先用VS2019自带的打开VS2015X64本地命令行编译gtest工程测试安装自己写个测试工程,看看编译出来的…...
你好GPT-4o——对GPT-4o发布的思考与看法
你好GPT-4o 前言 2024年5月13日,OpenAI官网发布了他们的新一代自然语言处理交互系统——GPT-4o。这是OpenAI继GPT4之后又一个新的旗舰模型。 GPT-4o(“o”代表“omni”)是迈向更自然的人机交互的一步——它接受文本、音频、图像和视频的任意…...
QT 信号和槽 多对一关联示例,多个信号,一个槽函数响应,多个信号源如何绑定一个槽函数
三个顾客 Anderson、Bruce、Castiel 都要订饭,分别对应三个按钮,点击一个按钮,就会弹出给该顾客送饭的消息。注意这个例子只使用一个槽函数,而三个顾客名称是不一样的,弹窗时显示的消息不一样,这需要一些 技…...
宝塔nginx配置
将跟php有关的注释掉: 添加: #解决vue刷新404问题try_files $uri $uri/ /index.html; location /prod-api/ {proxy_set_header Host $http_host;proxy_set_header X-Real-IP $remote_addr;proxy_set_header REMOTE-HOST $remote_addr;proxy_set_header…...
容器化实践:DevOps环境下的容器交付流程
DevOps的兴起是为了应对市场和消费者对技术应用的不断增长的需求。它的目标是构建一个更快的开发环境,同时保持软件的高质量标准。DevOps还致力于在敏捷开发周期中提升软件的整体品质。这一目标的实现依赖于多种技术、平台和工具的综合运用。 结合容器化技术与DevO…...
Linux---sudo命令
文章目录 目录 文章目录 一.sudo命令简介 二.sudo 命令的特点 三.sudo 相关文件 四.sudo 命令授权配置 一.sudo命令简介 sudo 命令全称“SuperUser Do”,是Linux系统中的一个命令能够使普通用户以超级用户身份去执行某些命令。 二.sudo 命令的特点 sudo能够授权…...
前后端分离与实现 ajax 异步请求 和动态网页局部生成
前端 <!DOCTYPE html><!-- 来源 --> <!-- https://cloud.tencent.com/developer/article/1705089 --> <!-- https://geek-docs.com/ajax/ajax-questions/19_ajax_javascript_send_json_object_with_ajax.html --> <!-- 配合java后端可以监听 --&…...
Windows系统下CUDA、cuDNN与PyTorch的更新与安装全攻略
Windows系统下CUDA、cuDNN与PyTorch的更新与安装全攻略 文章目录 Windows系统下CUDA、cuDNN与PyTorch的更新与安装全攻略一、引言二、CUDA、cuDNN与PyTorch-GPU介绍三、安装准备1. 查看支持的CUDA版本2. 查看已安装的CUDA版本3. 查看支持的PyTorch版本 四、卸载旧版CUDA五、下载…...
Android Dialog使用汇总
Dialog分类 AlertDialog Dialog 类是对话框的基类,官方建议我们不要直接实例化它,而是使用其子类来获取实例。AlertDialog是系统提供的一个直接子类,它能帮助我们快速构建出不同类型的弹窗。接下来就看下各种类型弹窗的使用。 1、普通对话框…...
[数据集][目标检测]足球场足球运动员身份识别足球裁判员数据集VOC+YOLO格式312张4类别
数据集格式:Pascal VOC格式YOLO格式(不包含分割路径的txt文件,仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数):312 标注数量(xml文件个数):312 标注数量(txt文件个数):312 标注类别…...
学习分享-声明式的 HTTP 客户端OpenFeign
OpenFeign 详细介绍 最近在学习中有用到OpenFeign,也在网上查找了相关资料,做下分享。 一、概述 OpenFeign 是一个声明式的 HTTP 客户端,它使得调用 REST API 变得更加简单和直观。通过 OpenFeign,开发者只需定义接口并添加注解…...
(LeetCode 每日一题) 3442. 奇偶频次间的最大差值 I (哈希、字符串)
题目:3442. 奇偶频次间的最大差值 I 思路 :哈希,时间复杂度0(n)。 用哈希表来记录每个字符串中字符的分布情况,哈希表这里用数组即可实现。 C版本: class Solution { public:int maxDifference(string s) {int a[26]…...
进程地址空间(比特课总结)
一、进程地址空间 1. 环境变量 1 )⽤户级环境变量与系统级环境变量 全局属性:环境变量具有全局属性,会被⼦进程继承。例如当bash启动⼦进程时,环 境变量会⾃动传递给⼦进程。 本地变量限制:本地变量只在当前进程(ba…...
ubuntu搭建nfs服务centos挂载访问
在Ubuntu上设置NFS服务器 在Ubuntu上,你可以使用apt包管理器来安装NFS服务器。打开终端并运行: sudo apt update sudo apt install nfs-kernel-server创建共享目录 创建一个目录用于共享,例如/shared: sudo mkdir /shared sud…...
R语言AI模型部署方案:精准离线运行详解
R语言AI模型部署方案:精准离线运行详解 一、项目概述 本文将构建一个完整的R语言AI部署解决方案,实现鸢尾花分类模型的训练、保存、离线部署和预测功能。核心特点: 100%离线运行能力自包含环境依赖生产级错误处理跨平台兼容性模型版本管理# 文件结构说明 Iris_AI_Deployme…...
Redis相关知识总结(缓存雪崩,缓存穿透,缓存击穿,Redis实现分布式锁,如何保持数据库和缓存一致)
文章目录 1.什么是Redis?2.为什么要使用redis作为mysql的缓存?3.什么是缓存雪崩、缓存穿透、缓存击穿?3.1缓存雪崩3.1.1 大量缓存同时过期3.1.2 Redis宕机 3.2 缓存击穿3.3 缓存穿透3.4 总结 4. 数据库和缓存如何保持一致性5. Redis实现分布式…...
linux 错误码总结
1,错误码的概念与作用 在Linux系统中,错误码是系统调用或库函数在执行失败时返回的特定数值,用于指示具体的错误类型。这些错误码通过全局变量errno来存储和传递,errno由操作系统维护,保存最近一次发生的错误信息。值得注意的是,errno的值在每次系统调用或函数调用失败时…...
镜像里切换为普通用户
如果你登录远程虚拟机默认就是 root 用户,但你不希望用 root 权限运行 ns-3(这是对的,ns3 工具会拒绝 root),你可以按以下方法创建一个 非 root 用户账号 并切换到它运行 ns-3。 一次性解决方案:创建非 roo…...
CVE-2020-17519源码分析与漏洞复现(Flink 任意文件读取)
漏洞概览 漏洞名称:Apache Flink REST API 任意文件读取漏洞CVE编号:CVE-2020-17519CVSS评分:7.5影响版本:Apache Flink 1.11.0、1.11.1、1.11.2修复版本:≥ 1.11.3 或 ≥ 1.12.0漏洞类型:路径遍历&#x…...
libfmt: 现代C++的格式化工具库介绍与酷炫功能
libfmt: 现代C的格式化工具库介绍与酷炫功能 libfmt 是一个开源的C格式化库,提供了高效、安全的文本格式化功能,是C20中引入的std::format的基础实现。它比传统的printf和iostream更安全、更灵活、性能更好。 基本介绍 主要特点 类型安全:…...
UE5 音效系统
一.音效管理 音乐一般都是WAV,创建一个背景音乐类SoudClass,一个音效类SoundClass。所有的音乐都分为这两个类。再创建一个总音乐类,将上述两个作为它的子类。 接着我们创建一个音乐混合类SoundMix,将上述三个类翻入其中,通过它管理每个音乐…...
