Java使用Hutool工具类轻松生成验证码

news2024/12/23 14:23:20

👩🏽‍💻个人主页:阿木木AEcru

🔥 系列专栏:《Docker容器化部署系列》 《Java每日面筋》

💹每一次技术突破,都是对自我能力的挑战和超越。

目录

    • 一、效果展示
      • 1.1 扭曲干扰的验证码
      • 1.2 线条干扰的验证码
      • 1.3 圆圈干扰的验证码
    • 二、验证码应用场景
      • 2.1 注册验证
      • 2.2 登录保护
      • 2.3 重置密码
      • 2.4 防止恶意行为
      • 2.5 活动秒杀
      • 2.6 数据保护
      • 2.7 交易安全
    • 三、Hutool工具类实现验证码生成
      • 3.1 引入依赖
      • 3.2 核心代码
      • 3.3 最简单实现方式
    • 四、设置背景颜色的坑
    • 五、结尾

一、效果展示

话不多说,先来看看效果图 ps:默认生成的背景颜色为白色的,这里我修改为了淡黄色(设置背景颜色这里有个坑,后面会讲到)

1.1 扭曲干扰的验证码

1.2 线条干扰的验证码

1.3 圆圈干扰的验证码

二、验证码应用场景

验证码是一种广泛应用于网络服务中的安全机制,用于验证用户身份,防止恶意软件和自动化脚本的滥用。以下是对验证码应用场景的详细阐述,包括不同场景下验证码的使用目的和实例说明。

2.1 注册验证

在用户注册账户时,验证码用于确保注册信息的真实性,防止恶意注册和自动化脚本的滥用。例如,在用户注册时,需要验证用户提供的手机号码是否有效,以防止注册时提供虚假或错误的手机号码。企业可以通过发送短信验证码来验证用户提供的手机号码。

2.2 登录保护

登录时使用验证码可以防止自动化工具尝试破解用户密码。在用户输入用户名或登录密码错误超过设定次数时,图形验证码出现,用以判断是否是机器人在测试数字密码,这时候就用图形验证来挡掉机器的攻击。

2.3 重置密码

当用户忘记密码时,验证码用于验证用户身份,确保密码重置请求的合法性。在重设密码流程里也需要输入验证码,图形验证码可视作后续步骤的触发,二者存在顺序关联性。

2.4 防止恶意行为

验证码用于防止恶意用户在平台上的刷单、刷票、恶意灌水等行为。例如,在论坛、投票等场景中,验证码有效抵御自动机刷赞和水军刷帖。

2.5 活动秒杀

在抢购、秒杀等活动中,验证码可以防止自动化脚本批量刷取奖励,保证活动的公平性。羊毛党频繁刷取奖励,导致真实用户无法获取奖励,验证码适用于抢购、秒杀、优惠券等活动场景。

2.6 数据保护

验证码用于保护网站内容和数据不被恶意爬虫爬取。例如,验证码适用于公告栏、论坛等内容网站,有效抵御自动机、爬虫盗取网页内容和数据。

2.7 交易安全

在进行金融交易或敏感操作时,验证码用于增强交易的安全性。例如,在线银行网站在用户进行转账操作时,可能会要求输入验证码来验证用户身份。

三、Hutool工具类实现验证码生成

3.1 引入依赖

<!--hutool工具包-->
<dependency>
	<groupId>cn.hutool</groupId>
	<artifactId>hutool-all</artifactId>
	<version>5.7.15</version>
</dependency

3.2 核心代码


@Slf4j
@RestController
@RequestMapping("/verify/code")
public class VerifyCodeController {

    //获取扭曲干扰的验证码
    @GetMapping("/createShearCaptcha")
    public void getShearCaptcha(HttpServletResponse response)
    {

        //定义图形验证码的长、宽、验证码字符数、干扰线宽度
        ShearCaptcha shearCaptcha = CaptchaUtil.createShearCaptcha(150, 50,4,3);
        //设置背景颜色
        shearCaptcha.setBackground(new Color(249, 251, 220));
        //生成四位验证码
        String code = RandomUtil.randomNumbers(4);
        //生成验证码图片
        Image image = shearCaptcha.createImage(code);
        //返回验证码信息
        responseCode(response, code, image);
    }

    //获取线条干扰的验证码
    @GetMapping("/createLineCaptcha")
    public void getLineCaptcha(HttpServletResponse response)
    {

        //定义图形验证码的长、宽、验证码位数、干扰线数量
        LineCaptcha lineCaptcha = CaptchaUtil.createLineCaptcha(150, 50,4,80);
        //设置背景颜色
        lineCaptcha.setBackground(new Color(249, 251, 220));
        //生成四位验证码
        String code = RandomUtil.randomNumbers(4);
        Image image = lineCaptcha.createImage(code);
        //返回验证码信息
        responseCode(response, code, image);
    }

    //获取圆圈干扰的验证码
    @GetMapping("/createCircleCaptcha")
    public void getCircleCaptcha(HttpServletResponse response)
    {

        //定义图形验证码的长、宽、验证码位数、干扰圈圈数量
        CircleCaptcha circleCaptcha = CaptchaUtil.createCircleCaptcha(150, 50,4,30);
        //设置背景颜色
        circleCaptcha.setBackground(new Color(249, 251, 220));
        //生成四位验证码
        String code = RandomUtil.randomNumbers(4);
        Image image = circleCaptcha.createImage(code);
        //返回验证码信息
        responseCode(response, code, image);
    }




    private static void responseCode(HttpServletResponse response, String code, Image image) {
        response.setContentType("image/jpeg");
        response.setHeader("Pragma", "no-cache");
        response.setHeader("Cache-Control", "no-cache");
        String uuidStr = UUID.randomUUID().toString().replace("-", "");
        log.info("生成验证码 uuidStr:{} ,code:{}",uuidStr, code);
        response.setHeader("verifyCodeUuid",uuidStr);
        try {
            BufferedImage bufferedImage = toBufferedImage(image);
            // 创建一个ByteArrayOutputStream,用于存储图片数据
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            // 写入图片数据到ByteArrayOutputStream
            ImageIO.write(bufferedImage, "jpeg", baos);
            // 将ByteArrayOutputStream转换为ByteArrayInputStream
            byte[] imageInBytes = baos.toByteArray();
            //输出
            IoUtil.write(response.getOutputStream(), true, imageInBytes);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}

在这里响应的时候,我在请求头中加了个verifyCodeUuid (验证码唯一标识), 是用于后续 校验验证码使用的,可以将验证码存在redis ,存储的key的话可以使用 【前缀+请求ip+verifyCodeUuid 】 形式来进行存储,后续获取校验的时候也是一样的key,前端就需要将verifyCodeUuid 和用户输入的验证码一并传过来。这是一种简单的实现,具体 实现还需看具体业务,这里供参考。

3.3 最简单实现方式


    @GetMapping("/createShearCaptchaV2")
    public void getShearCaptchaV2(HttpServletResponse response)
    {
        //定义图形验证码的长、宽、验证码字符数、干扰线宽度
        ShearCaptcha shearCaptcha = CaptchaUtil.createShearCaptcha(150, 50,4,3);
        response.setContentType("image/jpeg");
        response.setHeader("Pragma", "no-cache");
        response.setHeader("Cache-Control", "no-cache");
        String uuidStr = UUID.randomUUID().toString().replace("-", "");
        log.info("生成验证码 uuidStr:{} ,code:{}",uuidStr, shearCaptcha.getCode());
        response.setHeader("verifyCodeUuid",uuidStr);
        try {
            //输出
            shearCaptcha.write(response.getOutputStream());
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

这里使用了默认的样式,背景色为白色。

四、设置背景颜色的坑

一开始,我是使用了3.3中的方式来返回验证码,但是需求背景颜色是需要灰色的,然后我就在3.3的基础上加上了

shearCaptcha.setBackground(new Color(233, 233, 233));

然后生成出来的图形还是白色的,就很纳闷,于是我就点进去了原码看了一下。

然后就发现 这个传输的对象是在首次创建验证码的时候初始化的,后面设置背景颜色的时候也不会去给它重新赋值, 就导致了加上背景颜色设置后也不生效的问题。

五、结尾

感谢观看至此,希望该文章能够帮助到您提升知识和技能。如果您喜欢我的内容,请不要忘记点赞和分享哦!👍

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

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

相关文章

C++学习第十一天——vector的模拟实现

✨ 生于火焰&#xff0c;落俗不可避免&#xff0c;但浪漫至死不渝 &#x1f30f; &#x1f4c3;个人主页&#xff1a;island1314 &#x1f525;个人专栏&#xff1a;C学习 &#x1f680; 欢迎关注&#xff1a;&#x1f44d;点赞 &…

白玉兰之争王一博vs王阳谁将摘得男主荣耀

白玉兰之争&#xff1a;王一博VS王阳&#xff0c;谁将摘得男主荣耀&#xff1f;在这个星光璀璨的夜晚&#xff0c;白玉兰奖的提名名单犹如一道耀眼的闪电&#xff0c;点燃了娱乐圈的硝烟。其中&#xff0c;王一博与王阳入围白玉兰男主角的消息更是引发了热议狂潮。两位实力派演…

使用pytorch构建ResNet50模型训练猫狗数据集

数据集 1.导包 import torch import torch.nn as nn import torch.optim as optim from torch.utils.data import DataLoader from torchvision import datasets, transforms, models import numpy as np import matplotlib.pyplot as plt import os from tqdm.auto import t…

iOS ------ 多线程 GCD

一&#xff0c;GCD简介 GCD是Apple开发的一个多线程的较新的解决方案。它主要用于优化应用程序以支持多核处理器以及其他对称处理系统。它是一个在线程池模式的基础上执行的并发任务。 为什么要使用GCD&#xff1f; GCD&#xff01;可用于多核的并行运算GCD会自动利用更多的…

dockers安装mysql

1.dockerhub上搜索自己需要安装得镜像版本 dockerhub网址&#xff1a;https://hub-stage.docker.com docker pull mysql:5.7 #下载自己需要得版本2.启动容器实例&#xff0c;并且挂载容器数据卷 docker run -d -p 3306:3306 --privilegedtrue \ -v /home/mysql/log:/var/log/…

模拟 CMOS 逆变器的开关功耗

我们不会进一步讨论静态功耗。相反&#xff0c;本文和下一篇文章将介绍 SPICE 仿真&#xff0c;以帮助您更全面地了解逆变器的不同类型的动态功耗。本文重点讨论开关功率——输出电压变化时电容充电和放电所消耗的功率。 LTspice 逆变器实施 图 1 显示了我们将使用的基本 LTsp…

小白跟做江科大32单片机之OLED驱动

原理部分 代码测试 1.江科大老师提供的以下代码文件放入工程中&#xff0c;进行测试 2.正常显示即可

一点连接千家银行,YonSuite让“企业资金”实时在线

用友YonSuite作为全场景SaaS应用服务&#xff0c;是成长型企业实现数智转型的不二选择。多年来&#xff0c;凭借不断的技术革新&#xff0c;通过与千家银行的一站式连接&#xff0c;实现了企业资金的实时在线管理&#xff0c;为成长型企业带来了极大的便利和效益。这一举措不仅…

618适合入手哪些数码好物?实用数码好物清单分享,错过拍烂大腿!

在一年一度的618购物狂欢节里&#xff0c;许多数码爱好者们都在这次盛大的购物盛宴中觅得心仪的数码好物&#xff0c;数码产品不仅改变了我们的生活方式&#xff0c;更让我们享受到了前所未有的便捷和乐趣&#xff0c;那么在这个618&#xff0c;哪些数码好物值得我们入手呢&…

在线IP检测如何做?代理IP需要检查什么?

当我们的数字足迹无处不在&#xff0c;隐私保护显得愈发重要。而代理IP就像是我们的隐身斗篷&#xff0c;让我们在各项网络业务中更加顺畅。 我们常常看到别人购买了代理IP服务后&#xff0c;通在线检测网站检查IP&#xff0c;相当于一个”售前检验““售后质检”的作用。但是…

Golang:使用Base64Captcha生成数字字母验证码实现安全校验

Base64Captcha可以在服务端生成验证码&#xff0c;以base64的格式返回 为了能看到生成的base64验证码图片&#xff0c;我们借助gin go get -u github.com/mojocn/base64Captcha go get -u github.com/gin-gonic/gin文档的示例看起来很复杂&#xff0c;下面&#xff0c;通过简…

豆包浏览器插件会造成code标签内容无法正常显示

启用状态&#xff1a;页面的代码会显示不正常 禁用后&#xff0c;正常显示 害得我重置浏览器设置&#xff0c;一个个测试

leetcode刷题记录28-427. 建立四叉树

问题描述 给你一个 n * n 矩阵 grid &#xff0c;矩阵由若干 0 和 1 组成。请你用四叉树表示该矩阵 grid 。 你需要返回能表示矩阵 grid 的 四叉树 的根结点。 四叉树数据结构中&#xff0c;每个内部节点只有四个子节点。此外&#xff0c;每个节点都有两个属性&#xff1a; val…

JVM学习-字节码指令集(三)

代码下载 操作数栈管理指令 如同操作一个普通数据结构中的堆栈那样&#xff0c;JVM提供的操作数栈管理指令&#xff0c;可以用于直接操作数栈的指令 将一个或两个元素从栈顶弹出&#xff0c;并且直接废弃&#xff1a;pop,pop2复制栈顶一个或两个数值并将复制值成双份的复制值…

【全开源】餐饮点餐系统源码(ThinkPHP+FastAdmin+UniApp)

开启智能餐饮新时代的钥匙 基于ThinkPHPFastAdminUniApp开发的餐饮点餐系统&#xff0c;主要应用于餐饮&#xff0c;例如早餐、面馆、快餐、零食小吃等快捷扫码点餐需求&#xff0c;标准版本仅支持先付款后就餐模式&#xff0c;高级版本支持先付后就餐和先就餐后付费两种模式。…

昆虫记思维导图,超详细解读

《昆虫记》是法国杰出昆虫学家、文学家法布尔的传世佳作&#xff0c;它不仅是一部研究昆虫的科学巨著&#xff0c;同时也是一部脍炙人口的文学经典。在这部作品中&#xff0c;法布尔以其独特的视角和细腻的笔触&#xff0c;为我们揭示了一个神秘而精彩的昆虫世界。那么&#xf…

重生之 SpringBoot3 入门保姆级学习(11、日志的进阶使用)

重生之 SpringBoot3 入门保姆级学习&#xff08;11、日志的进阶使用&#xff09; 3.2.4 文件输出3.2.5 日志文档的归档与切割 3.2.4 文件输出 配置 application.properties # 日志文件名 如果不写路径默认就是在项目根路径建立 demo.log 文件 推荐写法 D:\\demo.log 路径 文…

为什么要使用动态代理IP?

一、什么是动态代理IP&#xff1f; 动态代理IP是指利用代理服务器来转发网络请求&#xff0c;并通过不断更新IP地址来保护访问者的原始IP&#xff0c;从而达到匿名访问、保护隐私和提高访问安全性的目的。动态代理IP在多个领域中都有广泛的应用&#xff0c;能够帮助用户…

面试题:计算机网络中的七四五是什么?

面试题&#xff1a;计算机网络中的七四五是什么&#xff1f; 计算机网络中说的七四五是指&#xff1a;OSI 七层模型、TCP/IP 四层模型、OSI 与 TCP/IP 的综合五层模型 OSI 七层模型 OSI 将计算机网络分为了七层&#xff0c;每一层抽象底层的内容&#xff0c;并遵守一定的规则…

【错题集-编程题】过桥(BFS)

牛客对应题目链接&#xff1a;过桥 (nowcoder.com) 一、分析题目 类似层序遍历的思想。 二、代码 //值得学习的代码 #include <iostream>using namespace std;const int N 2010;int n; int arr[N];int bfs() {int left 1, right 1;int ret 0;while(left < right)…