基于SpringBoot和Hutool工具包实现的验证码案例

目录

验证码案例

1. 需求

2. 准备工作

3. 约定前后端交互接口 

需求分析

接口定义

4. Hutool 工具介绍

5. 实现验证码

后端代码 

前端代码

6. 运行测试 


验证码案例

随着安全性的要求越来越高,目前项目中很多都会使用验证码,只要涉及到登录,绝大多数都会有验证的要求,验证码的形式也是多种多样,更复杂的图形验证码和行为验证码已经成为了更流行的趋势。

验证码的实现方式很多,可以前端实现,也可以后端实现。网上也有比较多的插件或者工具包可以使用,这里选择使用 Hutool工具包 来实现一个简单的验证码案例。完整代码见文章末尾。

1. 需求

最终实现的验证码界面如下图所示:

1. 页面生成验证码

2. 输入验证码,点击提交,验证用户输入验证码是否正确且是否超时,正确且未超时则进行页面跳转,错误或已超时则进行提示,并更换验证码

2. 准备工作

创建SpringBoot项目,引入Spring-Web-MVC和Lombok的依赖包,前端界面会在后面提供.

3. 约定前后端交互接口 

需求分析

后端需要提供两个服务:

  1. 生成验证码,并返回验证码.
  2. 校验验证码是否正确.

接口定义

1)生成验证码

请求: 

请求URL:/captcha/get

 响应:浏览器显示图片内容

浏览器给服务器发送一个 /captcha/get 请求,服务器返回一个图片,浏览器显示在页面上

2)校验验证码是否正确

请求:

请求URL:/captcha/check
请求参数:captcha=验证码字符串

响应:

true or false
根据用户输入的验证码,校验验证码是否正确,并判断验证码是否超时

4. Hutool 工具介绍

Hutool官网:https://hutool.cn/

Hutool参考文档:https://hutool.cn/docs/#/

要使用Hutool工具包,需要在pom.xml文件中添加对应的依赖,参考文档中有详细介绍:

<dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>5.8.16</version>
</dependency>

在Hutolol参考文档中找到图形验证码部分:

接下来可以就可以参考Hutool工具提供的方法,快速生成验证码,里面的介绍非常清晰,很容易看懂。此处使用如下格式验证码:

5. 实现验证码

项目目录结构如下:

后端代码 

实现接口

import cn.hutool.captcha.CaptchaUtil;
import cn.hutool.captcha.LineCaptcha;
import cn.hxxy.captchademo.config.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 {@Autowiredprivate CaptchaProperties captchaProp;@RequestMapping("/get")public void getCaptcha(HttpServletResponse response, HttpSession session) {//定义图形验证码的长和宽(配置默认值)LineCaptcha lineCaptcha = CaptchaUtil.createLineCaptcha(captchaProp.getWidth(), captchaProp.getHeight());//细节问题,不影响程序//设置返回类型response.setContentType("image/jpeg");//静止缓存response.setHeader("Progma", "No-cache");try {//图形验证码写出,可以写出到文件,也可以写出到流lineCaptcha.write(response.getOutputStream());//同时将验证码内容和当前时间戳存储到Session中//此处Session的键可以配置成常量session.setAttribute(captchaProp.getSession().getKey(), lineCaptcha.getCode());session.setAttribute(captchaProp.getSession().getDate(), new Date());//关流response.getOutputStream().close();} catch (IOException e) {throw new RuntimeException(e);}}//验证码生效时间限制private static final long VALID_MILLIS_TIME = 60 * 1000;@RequestMapping("/check")public boolean checkCaptcha(String captcha, HttpSession session) {//保证传过来的参数是合法的if (StringUtils.hasLength(captcha)) {//根据配置的默认session信息获取key和dateString key = (String) session.getAttribute(captchaProp.getSession().getKey());Date date = (Date) session.getAttribute(captchaProp.getSession().getDate());//1.验证码正确(不区分大小写)  2.验证码还未失效return key.equalsIgnoreCase(captcha)&& System.currentTimeMillis() - date.getTime() < VALID_MILLIS_TIME;}return false;}
}

代码解析:

  1. 通过@Autowired注解注入了一个CaptchaProperties对象,这个对象是用来配置图形验证码的属性的。使用这种方式是因为代码中的有些属性可能会在别处使用,且它们都是固定的,例如图形验证码的长和宽,Session的字段名等。将这些属性封装在一个对象中,并通过读取配置文件的方式绑定属性值。

  2. 在@RequestMapping注解的getCaptcha方法中,使用Hutool包的CaptchaUtil.createLineCaptcha方法创建了一个图形验证码对象lineCaptcha,其大小由配置文件中的captchaProp.getWidth()和captchaProp.getHeight()决定。然后,将验证码内容和当前时间戳存储到HttpSession中,以便后续校验验证码的时候使用。最后,将图形验证码写出到HttpServletResponse的输出流中,以返回给前端页面显示。

  3. 在@RequestMapping注解的checkCaptcha方法中,首先判断传入的验证码参数是否合法。如果合法,则从HttpSession中获取存储的验证码内容和时间戳信息,并进行比较。如果验证码正确且未过期,则返回true,否则返回false。

CaptchaProperties类的实现和配置文件(.yml)信息如下:

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;@Data
@Configuration
@ConfigurationProperties(prefix = "captcha")
public class CaptchaProperties {private Integer width;private Integer height;private Session session; //使用自定义的Session类@Datapublic static class Session {private String key;private String date;}
}
spring:application:name:captcha-democaptcha:width: 200height: 100session:key: CAPTCHA_SESSION_KEYdate: CAPTCHA_SESSION_DATE

此处还没有前端代码,但是已经可以先测试了,通常写好一个接口就可以测试一下。

启动项目,再访问 http://127.0.0.1:8080/captcha/get  显示验证码图片如下:

通过 Fiddler 进行抓包,HTTP请求和响应数据如下,图片就在响应的body部分:

前端代码

注意前端代码要放在resources的static目录下

index.html(重点关注script标签内的代码):

<!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();//使用attr()方法修改src属性值,获取一个新的验证码图片,后面添加一个时间戳参数来保证每次请求的验证码图片都是不同的$(this).attr('src', '/captcha/get?dt=' + new Date().getTime());});//点击提交按钮,进行验证码校验$("#checkCaptcha").click(function () {$.ajax({url: "/captcha/check",type: "post",data: {captcha: $("#inputCaptcha").val()},success: function (result) {if (result) {location.href = "success.html";} else {alert("验证码错误或已超时");//验证码错误,重新生成验证码$("#verificationCodeImg").attr('src', '/captcha/get?dt=' + new Date().getTime());$("#inputCaptcha").val("");}}});});</script>
</body></html>

JavaScript代码中主要包含两部分逻辑:

  1. 点击图片,切换验证码: 当id为"verificationCodeImg"的图片被点击时,会触发click事件的回调函数。回调函数通过修改图片的src属性,向后端发送一个请求来获取新的验证码图片,并使用当前时间戳作为参数,以确保每次请求的验证码图片都是不同的。最后,将获取到的新图片显示出来。

  2. 点击提交按钮,进行验证码校验: 当id为"checkCaptcha"的按钮被点击时,会触发click事件的回调函数。回调函数通过使用jQuery的ajax方法发送一个POST请求到"/captcha/check"接口,并传递了一个名为"captcha"的参数,该参数的值为id为"inputCaptcha"的输入框中用户输入的验证码。

    在请求成功后的回调函数中,会根据后端返回的结果(result)进行处理。如果校验成功,则跳转到"success.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>

6. 运行测试 

启动项目,浏览器访问 http://127.0.0.1:8080/index.html 或 http://localhost:8080/index.html

输入错误的验证码: 

提示正确,且验证码能正确刷新,超时同样会提示以上错误。且点击验证码图片时,会重新生成验证码。

输入正确的验证码:

验证成功,页面正确跳转,测试完成。

完整代码:https://gitee.com/lv-jiacong/Java-EE/tree/master/captcha-demo/src

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/16107.shtml

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

相关文章

Liunx系统中修改文件的创建时间以及访问时间

在Linux系统中&#xff0c;可以使用touch命令来修改文件的时间戳。以下是一些常用的touch命令选项&#xff1a; &#xff08;其实在MacOS中也适用&#xff09; 修改访问时间&#xff08;Access Time&#xff09;和修改时间&#xff08;Modification Time&#xff09;&#xf…

Celery的Web监控工具Flower

1 简介Flower Flower官网 Flower是一个WEB端的监控工具&#xff0c;可以监控Celery的消费者。但是WEB端的监控对于监控系统来说&#xff0c;有个屁用&#xff0c;有用的是监控告警。还好Flower不是全部是垃圾&#xff0c;它提供的Prometheus的监控端点。然而。。。。。如何保证…

CorelCAD v2022.5 解锁版 安装教程(2D制图 3D设计和打印的简化软件)

前言 CorelCAD&#xff0c;加拿大Corel公司开发的一款适用于2D制图、3D设计和打印的简化版CAD软件。它是款专业的2D制图和3D设计软件&#xff0c;拥有行业标准文件兼容性&#xff0c;支持 .DWG、.STL、.PDF、 .CDR*等文件格式&#xff0c;轻松实现协作和项目共享&#xff0c;利…

学 Go 具体能干什么?

学习 Go (Golang) 后&#xff0c;你可以从事许多不同的工作和项目&#xff0c;Go 语言以其高性能、并发处理和简洁的语法而闻名&#xff0c;特别适合以下几个领域&#xff1a; 1. 后端开发 Go 在后端开发中非常流行&#xff0c;特别适合构建高性能的 Web 服务和 API。 Web 框…

【机器学习】基于核的机器学习算法(Kernel-based Algorithms):原理,应用与优化

&#x1f440;传送门&#x1f440; 文章引言&#x1f50d;&#x1f340;核函数的概念&#x1f680;基于核的算法原理&#x1f496;基于核的算法应用&#x1f41f;支持向量机&#xff08;SVM&#xff09;&#x1f4d5;核主成分分析&#xff08;KPCA&#xff09; &#x1f340;未…

大数据信用报告查询有哪些作用?哪个平台更好?

大数据信用是基于大数据技术&#xff0c;通过大数据系统生成的大数据信用报告&#xff0c;报告收集了查询人在非银环境下的申贷数据以及履约行为和信用风险的综合性报告。很多人都会问&#xff0c;大数据信用报告查询有哪些作用?哪个查询平台更好的疑问&#xff0c;下文就详细…

C++STL---string知识汇总

前言 我们现在开始CSTL的学习&#xff0c;从这时开始我们就要锻炼自己查看英文文档的能力&#xff0c;每种数据结构都有上百个接口函数&#xff0c;我们把他们全部记下来是不可能的&#xff0c;所以我们只记最常见的20几个接口&#xff0c;其他的大概熟悉有什么功能&#xff0…

深入JVM元空间以及弹性伸缩机制

个人博客 深入JVM元空间以及弹性伸缩机制 | iwts’s blog JVM内存模型中元空间所在位置 即在JVM运行时的内存模型。总体上有这样的图&#xff1a; 元空间 上面的图其实有点不太准。方法区本质上只是JVM的一个标准&#xff0c;不同JVM在不同版本下都可能有不同的实现&#x…

Matlab中函数或变量 ‘eeglab‘ 无法识别

EEGLAB 没有安装或添加到 MATLAB 路径中&#xff1a; 确保已经安装了 EEGLAB&#xff0c;并且将其添加到 MATLAB 的路径中。您可以通过在 MATLAB 命令窗口中运行 which eeglab 来检查是否能够找到 EEGLAB。 EEGLAB 函数路径设置错误&#xff1a; 如果已经安装了 EEGLAB&#x…

可以免费试用得微信辅助工具wetool升级版,可以群发,可以清理僵尸粉,可以自动回复,可以批量添加

今天给大家推荐一款我们目前在使用的电脑群发工具掘金小蜜&#xff0c;不仅可以无限多开&#xff0c;方便你同时管理多个账号&#xff0c;群发功能更是十分强大&#xff0c;轻松释放你的双手。 掘金小蜜&#xff08;只支持Win7及以上操作系统&#xff0c;没有推Mac版和手机客户…

【知识拓展】LocalTunnel-高性价比的内网穿透工具(2)

前言 上一篇通过ngrok进行内网穿透&#xff0c;有几个问题&#xff1a; ①需要注册&#xff0c;而且注册需要科学上网&#xff0c;相对麻烦 ②安装配置相对麻烦&#xff0c;authtoekn有限制 上述相对&#xff0c;指的是在非生产环境中做一个简单内网穿透&#xff0c;相对于…

neo4j开放远程连接

注&#xff1a;本博客所用neo4j版本为社区5.12版 第一步&#xff1a;修改neo4j配置文件 首先找到neo4j的安装位置&#xff0c;点击进入conf文件夹&#xff0c;随后点击neo4j.conf文件&#xff0c;在“Network connector configuration”下面的单元中找到server.default_liste…

汽车IVI中控开发入门及进阶(二十):显示技术之LCDC

TFT LCD=Thin Film Transistor Liquid Crystal Display LCDC=LCD Controller 薄膜晶体管液晶显示器(TFT LCD)控制器在驱动现代显示技术的功能和性能方面起着关键作用。它们充当屏幕后面的大脑,仔细处理数字信号,并将其转化为精确的命令,决定每个像素的行为,决定它们的…

计算机网络基本概念

文章目录 情景带入一些基本概念网络网络编程&#xff1a;7层网络模型OSI&#xff1a;TCP/IP Protocol Architecture Layers与OSI的对应关系SocketClient-Server Application报文段&#xff1a;传输协议&#xff1a;Mac地址IP地址端口URL 情景带入 随着时代的发展&#xff0c;我…

STM32—HAL-PWM-舵机180(每个频率对应每个角度)

1开启时钟 2开启定时器和通道设置为PWM模式 3将定时时间设置为50Hz(20ms)//每25为1ms 4代码编写 4.1开启PWM 4.2改PWM的占空比 4.3效果0~180度在0度 源码 /* USER CODE BEGIN Header */ /******************************************************************************…

《C++ Primer Plus》第十一章复习题和编程练习

这里写目录标题 一、复习题二、编程练习 一、复习题 1. 使用成员函数为Stonewt类重载乘法运算符&#xff0c;该运算符将数据成员与double类型的值相乘。注意&#xff0c;当用英石和磅表示时&#xff0c;需要进位。也就是说&#xff0c;将10英石8磅乘以2等于21英石2磅。 答&am…

Imperva 导致的ORAbase 乱码

DBCA Failing Because Of Garbage Characters In ORACLE_BASE Variable (Doc ID 2947963.1)​编辑To Bottom In this Document Symptoms Changes Cause Solution APPLIES TO: Oracle Database Configuration Assistant - Version 19.14.0.0.0 and later Oracle Database - E…

本地镜像文件怎么导入docker desktop

docker tag d1134b7b2d5a new_repo:new_tag

PageHelper分页

文章目录 PageHelper分页ThreadLocalMap和ThreadLocal执行完PageHelper.startPage之后&#xff0c;分页参数存储到哪里了&#xff1f;Page和List的关系&#xff1f;PageInterceptor分页拦截器的作用&#xff1f;PageInfo的作用与结构&#xff1f;最后看下引入的pagehelper分页依…

YoloV1模型

You Only Look Once 文章目录 You Only Look Once置信度定义类别条件概率NMSnp.maxmiumnp.argsort() Yolov1直接采用网络特征输出&#xff0c;实现置信度预测、分类、边界框回归&#xff1b; 核心内容总结&#xff1a; 输入图像划分为 S S 网格。如果对象的中心落入网格单元中…