您现在的位置是:首页 > 编程 > 

Spring Boot 整合Hutool

2025-07-24 01:54:30
Spring Boot 整合Hutool Spring Boot 整合Hutool-captcha实现图形验证码 推荐框架 基于SpringBoot+Vue前后端分离的Java快速开发框架 项目简介:基于 JDK 17、Spring Boot 、Spring Security 6、JWT、Redis、Mybatis-Plus、Knife4j等构建后端,基于Vue 、Element-

Spring Boot 整合Hutool

Spring Boot 整合Hutool-captcha实现图形验证码

推荐框架 基于SpringBoot+Vue前后端分离的Java快速开发框架 项目简介:基于 JDK 17、Spring Boot 、Spring Security 6、JWT、Redis、Mybatis-Plus、Knife4j等构建后端,基于Vue 、Element-Plus 、TypeScript等构建前端的分离单体权限管理系统。 项目地址: 后端: gitee: .git gitcode: .git 前端: gitee: .git .git 觉着有帮助,给个Star再走呗 搜“Harry技术”,关注我,带你看不一样的人间烟火!

在整合技术框架的时候,想一个图形验证码相关的框架,看到很多验证码不在更新了或者是在中央仓库下载不下来,还需要多引入依赖。后面看到了Hutool 图形验证码(Hutool-captcha)中对验证码的实现,提供了:线段干扰验证码、圆圈干扰验证码、扭曲干扰验证码以及自定义验证码。就此验证码在项目中的使用展开说明。

Hutool-captcha
验证码需求分析:代码语言:context复制
1. 生成验证码,点击图片可进行刷新
2. 输入验证码,点击提交,验证用户输入验证码是否正确
项目创建

首先创建项目这里使用的Spring boot + JDK17,并引入相关依赖

pom.xml

代码语言:xml复制
<properties>
        <java.version>17</java.version>

        <hutool.version>5.8.26</hutool.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-captcha</artifactId>
        </dependency>
    </dependencies>
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>cn.hutool</groupId>
                <artifactId>hutool-bom</artifactId>
                <version>${hutool.version}</version>
                <type>pom</type>
                <!-- 注意这里是import -->
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

import方式的使用说明

如果你想像Spring-Boot一样引入Hutool,再由子模块决定用到哪些模块,你可以在父模块中加入:

代码语言:xml复制
<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-bom</artifactId>
            <version>${hutool.version}</version>
            <type>pom</type>
            <!-- 注意这里是import -->
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

在子模块中就可以引入自己需要的模块了:

代码语言:xml复制
<dependency>
    <groupId>cn.hutool</groupId>
    <artifactId>hutool-captcha</artifactId>
</dependency>

使用import的方式,只会引入hutool-bom内的dependencyManagement的配置,其它配置在这个引用方式下完全不起作用。

exclude方式

如果你引入的模块比较多,但是某几个模块没用,你可以:

代码语言:xml复制
<dependencies>
    <dependency>
        <groupId>cn.hutool</groupId>
        <artifactId>hutool-bom</artifactId>
        <version>${hutool.version}</version>
        <!-- 加不加这句都能跑,区别只有是否告警  -->
        <type>pom</type>
        <exclusi>
            <exclusion>
                    <groupId>cn.hutool</groupId>
                    <artifactId>hutool-system</artifactId>
            </exclusion>
        </exclusi>
    </dependency>
</dependencies>

这个配置会传递依赖hutool-bom内所有dependencies的内容,当前hutool-bom内的dependencies全部设置了version,就意味着在maven resolve的时候hutool-bom内就算存在dependencyManagement也不会产生任何作用。

定义接口:代码语言:context复制
1. 生成验证码,并返回
2. 校验验证码是否正确
接口定义
代码语言:context复制
1.  生成验证码
[URL]
GET /captcha/getCaptcha
[请求参数]
[响应]
{
    "uuid": "fc2b40825f20470bb4f5d9868b856f",
    "img": "data:image/png;base64,issaxxxxxxxxgg=="
}

uuid 是为了方便在真实项目使用中做区分
代码语言:context复制
2. 校验验证码是否正确
[URL]
POST /captcha/check
[请求参数]
{"uuid":"4b4b0bf114e9f840507b7babd620","code":""}
[响应]
{
   true
}

根据用户输入的验证码,校验验证码是否正确,校验成功,返回true;校验失败,返回false
定义 CaptchaController
代码语言:java复制
@Slf4j
@RestController
@RequestMapping("/captcha")
@AllArgsCtructor
public class CaptchaController {

    private final SysCaptchaService sysCaptchaService;

    /**
     * 生成验证码
     */
    @GetMapping("/getCaptcha")
    public CaptchaResult getCaptcha(HttpSession session) {
        return sysCaptchaService.getCaptcha(session);
    }

    /**
     * 验证码校验
     *
     * @param param 验证码参数
     */
    @PostMapping("/check")
    public boolean checkCaptcha(@RequestBody CaptchaValidateParam param, HttpSession session) {
        String uuid = param.getUuid();
        String captcha = param.getCode();
        if (StrUtil.isEmpty(uuid) || StrUtil.isEmpty(captcha)) {
            ("验证码参数不能为空");
            return false;
        }
        log.info("接收到验证码: uuId:{}, 验证码:{}", uuid, captcha);
        // 参数校验
        return sysCaptchaService.validate(uuid, captcha, session);
    }
}

由于当用户输入验证码时,我们需要进行校验,因此,我们需要对生成的验证码进行存储,同时,需要存储验证码的生成时间,以便判断验证码是否超时

代码语言:java复制
public class Ctants {
    public static final String CAPTCHA_CODE = "code";
    public static final String CAPTCHA_UUID = "uuid";
}
  • SysCaptchaService
代码语言:java复制
public interface SysCaptchaService {

    /**
     * 获取验证码
     *
     * @param session
     * @return
     */
    CaptchaResult getCaptcha(HttpSession session);

    /**
     * 验证码效验
     *
     * @param uuid
     * @param code
     * @param session
     * @return
     */
    boolean validate(String uuid, String code, HttpSession session);
}
  • SysCaptchaServiceImpl
代码语言:java复制
@Service
@RequiredArgsCtructor
@Slf4j
public class SysCaptchaServiceImpl implements SysCaptchaService {

    private final CaptchaProperties captchaProperties;
    private final CodeGenerator codeGenerator;
    private final Font captchaFont;


    @Override
    public CaptchaResult getCaptcha(HttpSession session) {


        String captchaType = captchaProperties.getType();
        int width = captchaProperties.getWidth();
        int height = captchaProperties.getHeight();
        int interfereCount = captchaProperties.getInterfereCount();
        int codeLength = captchaProperties.getCode().getLength();

        AbstractCaptcha captcha;
        if (CaptchaTypeEnums.().equalsIgnoreCase(captchaType)) {
            captcha = (width, height, codeLength, interfereCount);
        } else if (CaptchaTypeEnums.().equalsIgnoreCase(captchaType)) {
            captcha = (width, height, codeLength);
        } else if (CaptchaTypeEnums.().equalsIgnoreCase(captchaType)) {
            captcha = (width, height, codeLength, interfereCount);
        } else if (CaptchaTypeEnums.().equalsIgnoreCase(captchaType)) {
            captcha = (width, height, codeLength, interfereCount);
        } else {
            throw new IllegalArgumentException("Invalid captcha type: " + captchaType);
        }
        captcha.setGenerator(codeGenerator);
        captcha.setTextAlpha(captchaProperties.getTextAlpha());
        captcha.setFont(captchaFont);

        String code = captcha.getCode();
        String imageBase64Data = captcha.getImageBase64Data();

        // 验证码文本缓存至Redis,用于登录校验
        String uuid = IdUtil.fastSimpleUUID();

        session.setAttribute(Ctants.CAPTCHA_CODE, code);
        session.setAttribute(Ctants.CAPTCHA_UUID, uuid);

        return CaptchaResult.builder().img(imageBase64Data).uuid(uuid).build();
    }

    @Override
    public boolean validate(String uuid, String code, HttpSession session) {
        // session中获取验证码
        String captchaCode = (String) session.getAttribute(Ctants.CAPTCHA_CODE);
        return codeGenerator.verify(captchaCode, code);
    }

将用户输入的验证码与存储在 session 中的验证码进行对比,判断其是否相同,若相同且在1min内,则验证成功

前端代码
代码语言:html复制
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        #app {
            font-family: Avenir, Helvetica, Arial, sans-serif;
            -webkit-font-smoothing: antialiased;
            -moz-osx-font-smoothing: grayscale;
            text-align: center;
            color: #2ce50;
            margin-top: 60px;
        }

        #inputCaptcha {
            height: 0px;
            vertical-align: middle;
        }

        #verificationCodeImg {
            vertical-align: middle;
        }

        #checkCaptcha {
            height: 40px;
            width: 100px;
            border: 1px solid #000;
            border-radius: 5px;
            margin-left: 10px;
            vertical-align: middle;
        }
    </style>
</head>
<script src=".6.4/js"></script>

<body>
<div id="app">
    <h1>{{ message }}</h1>
    <input type="text" v-model="inputCaptcha" id="inputCaptcha">
    <img id="verificationCodeImg" :src="captchaData.img" alt="验证码" @click="refreshCaptcha" title="看不清?换一张"/>
    <input type="button" value="提交" id="checkCaptcha" @click="checkCaptcha">
</div>

<script type="module">
    import {createApp, ref, onMounted} from '@/dist/js'

    createApp({
        setup() {
            ct message = ref('验证码校验')
            ct inputCaptcha = ref('')
            ct captchaData = ref({
                img: '',
                uuid: ''
            })

            ct refreshCaptcha = () => {
                $.ajax({
                    url: '/captcha/getCaptcha',
                    type: 'GET',
                    success: function (data) {
                        captchaData.value = data
                    }
                })
            }

            ct checkCaptcha = () => {
                ct  dataFrom = {
                    uuid: captchaData.value.uuid,
                    code: inputCaptcha.value
                }
                $.ajax({
                    url: '/captcha/check',
                    type: 'POST',
                    headers: {
                        'Content-Type': 'application/json'
                    },
                    data: JSO.stringify(dataFrom),
                    success: function (data) {
                        if (data) {
                            alert('验证码正确')
                            refreshCaptcha()
                        } else {
                            alert('验证码错误')
                            refreshCaptcha()
                        }
                    }
                })
            }

            // 页面加载完成后,刷新验证码
            onMounted(() => {
                refreshCaptcha()
            })

            return {
                message,
                captchaData,
                inputCaptcha,
                refreshCaptcha,
                checkCaptcha
            }
        }
    }).mount('#app')
</script>
</body>
</html>

验证成功:

image-202411211426762

验证失败:

image-2024112114264665

为让验证码有多样性,这里将验证的生成放入了application.yml配置文件中,内容如下:

代码语言:yaml复制
# 验证码配置
captcha:
  # 验证码类型 circle-圆圈干扰验证码|gif-Gif验证码|line-干扰线验证码|shear-扭曲干扰验证码
  type: circle
  # 验证码宽度
  width: 10
  # 验证码高度
  height: 48
  # 验证码干扰元素个数
  interfere-count: 2
  # 文本透明度(0.0-1.0)
  text-alpha: 0.8
  # 验证码字符配置
  code:
    # 验证码字符类型 math-算术|random-随机字符
    type: math
    # 验证码字符长度,type=算术时,表示运算位数(1:个位数运算 2:十位数运算);type=随机字符时,表示字符个数
    length: 1
  # 验证码字体
  font:
    # 字体名称 Dialog|DialogInput|Monospaced|Serif|SansSerif
    name: SansSerif
    # 字体样式 0-普通|1-粗体|2-斜体
    weight: 1
    # 字体大小
    size: 20
  # 验证码有效期(秒)
  expire-seconds: 120

项目代码示例地址:

#感谢您对电脑配置推荐网 - 最新i3 i5 i7组装电脑配置单推荐报价格的认可,转载请说明来源于"电脑配置推荐网 - 最新i3 i5 i7组装电脑配置单推荐报价格

本文地址:http://www.dnpztj.cn/biancheng/1184313.html

相关标签:无
上传时间: 2025-07-22 08:20:37
留言与评论(共有 6 条评论)
本站网友 梨的功效与作用
11分钟前 发表
.git .git 觉着有帮助
本站网友 局面
6分钟前 发表
48 # 验证码干扰元素个数 interfere-count
本站网友 夹心层
22分钟前 发表
checkCaptcha } } }).mount('#app') </script> </body> </html>验证成功:image-202411211426762验证失败:image-2024112114264665为让验证码有多样性
本站网友 薰衣草精油的使用方法
8分钟前 发表
你可以在父模块中加入:代码语言:xml复制<dependencyManagement> <dependencies> <dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-bom</artifactId> <version>${hutool.version}</version> <type>pom</type> <!-- 注意这里是import --> <scope>import</scope> </dependency> </dependencies> </dependencyManagement>在子模块中就可以引入自己需要的模块了:代码语言:xml复制<dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-captcha</artifactId> </dependency>使用import的方式
本站网友 绿庭尚城业主论坛
29分钟前 发表
区别只有是否告警 --> <type>pom</type> <exclusi> <exclusion> <groupId>cn.hutool</groupId> <artifactId>hutool-system</artifactId> </exclusion> </exclusi> </dependency> </dependencies>这个配置会传递依赖hutool-bom内所有dependencies的内容