当前位置:

首页 > 编程开发 > java使用Hutool工具库实现图形验证码

java使用Hutool工具库实现图形验证码

Hutool工具库简化了Java图形验证码的实现过程。它提供ICaptcha接口和AbstractCaptcha抽象类,封装了验证码生成、校验等核心功能。开发者可快速创建线段、圆圈或扭曲干扰等样式的验证码,并通过集成到Web登录流程,实现包含时效性验证的安全校验机制。

本文目录

    在Ja va开发中,图形验证码是提升系统安全性的常见手段。自己从头实现一套,不仅要处理图形绘制、干扰线生成,还得考虑代码的随机性和安全性,确实费时费力。好在,我们有现成的轮子——Hutool工具库,它能让我们用极简的代码,快速实现专业级的验证码功能。

    关于Hutool的介绍

    Hutool是一个小而全的Ja va工具类库,通过静态方法封装,降低相关API的学习成本,提高工作效率,使Ja va拥有函数式语言般的优雅,让Ja va语言也可以“甜甜的”。

    Hutool中的工具方法来自每个用户的精雕细琢,它涵盖了Ja va开发底层代码中的方方面面,它既是大型项目开发中解决小问题的利器,也是小型项目中的效率担当;

    Hutool是项目中“util”包友好的替代,它节省了开发人员对项目中公用类和公用工具方法的封装时间,使开发专注于业务,同时可以最大限度的避免封装不完善带来的bug。

    要使用它,首先需要在项目的pom.xml文件中引入依赖:

    
        cn.hutool
        hutool-all
        5.8.26
    

    图形验证码

    介绍

    验证码功能位于cn.hutool.captcha包中,其核心是一个名为ICaptcha的接口。这个接口定义了几个关键方法,基本上涵盖了一个验证码组件应有的所有行为:

    createCode:创建验证码。实现类需要在这里生成随机的验证码字符串和对应的图片。

    getCode:获取验证码的文字内容,也就是用户需要识别的那个字符串。

    verify:校验用户输入的验证码是否正确。通常建议忽略大小写进行比对。

    write:将生成的验证码图片写出到指定的输出流中。

    其中,write方法只接收一个OutputStream参数,这样的设计很巧妙,使得实现类可以基于这个方法轻松扩展出写出到文件、响应流等多种方式。

    Hutool还提供了一个AbstractCaptcha抽象类作为ICaptcha的基础实现。它已经把验证码文本的生成、忽略大小写的验证、以及写出到流和文件这些通用逻辑都封装好了。作为开发者,我们通常只需要继承这个抽象类,并实现createImage方法来定义具体的图形生成规则即可,大大减少了重复劳动。

    LineCaptcha:实现线段干扰的验证码

    线段干扰是最经典的验证码样式之一。用Hutool实现起来,简单得超乎想象:

    import cn.hutool.captcha.CaptchaUtil;
    import cn.hutool.captcha.LineCaptcha;
    import cn.hutool.core.lang.Console;
    
    public class DemoController {
        public static void main(String[] args) {
            // 定义图形验证码的长和宽
            LineCaptcha lineCaptcha = CaptchaUtil.createLineCaptcha(200, 100);
    
            // 将图形验证码写出到文件
            lineCaptcha.write("d:/line.png");
            // 在控制台输出生成的验证码文本,方便调试
            Console.log(lineCaptcha.getCode());
            // 验证用户输入的“1234”是否正确
            lineCaptcha.verify("1234");
    
            // 如果需要,可以重新生成验证码
            lineCaptcha.createCode();
            lineCaptcha.write("d:/line.png");
            // 输出新的验证码
            Console.log(lineCaptcha.getCode());
            // 再次验证
            lineCaptcha.verify("1234");
        }
    }

    运行上面的代码,控制台会输出验证码内容,同时会在D盘根目录生成一张图片。效果如下:

    ja va使用Hutool工具库实现图形验证码

    这就是生成的带有线段干扰的图形验证码:

    ja va使用Hutool工具库实现图形验证码

    CircleCaptcha:实现圆圈干扰验证码

    如果你觉得线段干扰有点普通,想换点花样,圆圈干扰是个不错的选择。它用随机的小圆圈作为干扰元素,同样只需几行代码:

    import cn.hutool.captcha.CaptchaUtil;
    import cn.hutool.captcha.CircleCaptcha;
    import cn.hutool.core.lang.Console;
    
    public class CircleController {
        public static void main(String[] args) {
            // 定义图形验证码的长、宽、验证码字符数、干扰元素个数
            CircleCaptcha captcha = CaptchaUtil.createCircleCaptcha(200, 100, 4, 20);
            // 也可以直接new:CircleCaptcha captcha = new CircleCaptcha(200, 100, 4, 20);
            // 写出到文件
            captcha.write("d:/circle.png");
            Console.log(captcha.getCode());
            // 进行验证
            captcha.verify("1234");
        }
    }

    运行结果:

    ja va使用Hutool工具库实现图形验证码

    生成的验证码效果如下,可以看到背景布满了随机圆圈:

    ja va使用Hutool工具库实现图形验证码

    ShearCaptcha:实现扭曲干扰验证码

    想要进一步增强机器识别的难度?扭曲干扰验证码(ShearCaptcha)会把字符进行一定程度的扭曲和错切,对人眼来说可能稍微费点劲,但对机器识别程序挑战更大。

    import cn.hutool.captcha.CaptchaUtil;
    import cn.hutool.captcha.ShearCaptcha;
    import cn.hutool.core.lang.Console;
    
    public class ShearController {
        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");
            Console.log(captcha.getCode());
            captcha.verify("1234");
        }
    }

    运行结果:

    ja va使用Hutool工具库实现图形验证码

    看看生成的效果,字符是不是有了明显的扭曲感?

    ja va使用Hutool工具库实现图形验证码

    将线段干扰验证码集成到登录流程

    了解了基本用法,我们来看一个实战场景:如何把验证码集成到一个Web登录流程中。整个过程可以分为前端和后端协同工作:

    1. 前端发起请求:用户打开登录页,前端首先向后端发起一个请求,获取图形验证码图片。

    2. 后端生成并存储:后端接收到请求后,调用Hutool生成验证码图片和对应的正确文本。将图片流返回给前端的同时,必须把验证码文本和生成时间存入当前用户的Session中。

    3. 用户输入并提交:用户在前端页面看到验证码图片,输入识别出的字符,连同账号密码一起提交。

    4. 后端校验:后端收到提交后,先判断验证码输入是否为空。然后从当前Session中取出之前存储的正确验证码和生成时间。

    5. 双重验证:校验分两步:第一,比对用户输入的验证码(忽略大小写)与Session中存储的是否一致;第二,检查当前时间与验证码生成时间的时间差,是否在允许的有效期内(比如60秒)。

    6. 返回结果:只有两步验证都通过,后端才返回成功;否则返回失败。前端根据结果决定是跳转到成功页面,还是提示验证码错误或过期。

    后端代码实现

    首先,我们在application.yml中配置验证码的参数,这样以后修改尺寸或Session键名会非常方便:

    captcha:
      width: 200
      height: 100
      session:
        key: captcha_session_key
        date: captcha_session_date
    

    配置属性类:CaptchaProperties

    创建一个属性类来映射配置文件中的值:

    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;
    
        @Data
        public static class Session{
            private String key;
            private String date;
        }
    }

    核心控制器:CaptchaController

    这个控制器提供两个核心接口:一个是获取验证码图片,一个是校验用户输入的验证码。

    import cn.hutool.captcha.CaptchaUtil;
    import cn.hutool.captcha.LineCaptcha;
    import cn.hutool.core.lang.Console;
    import com.wmh.captcha.model.CaptchaProperties;
    import jakarta.servlet.http.HttpServletRequest;
    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 ja va.io.IOException;
    import ja va.util.Date;
    
    @RequestMapping("/captcha")
    @RestController
    public class DCaptchaController {
        // 设置验证码有效期为60秒
        private final static long session_valid_timeout = 60 * 1000;
    
        @Autowired
        private CaptchaProperties captchaProperties;
    
        @RequestMapping("/get")
        public void getCaptcha(HttpSession session, HttpServletResponse response){
            // 1. 使用配置的宽高创建线段验证码
            LineCaptcha lineCaptcha = CaptchaUtil.createLineCaptcha(captchaProperties.getWidth(), captchaProperties.getHeight());
            // 2. 设置响应头,告诉浏览器这是张图片
            response.setContentType("image/jpeg");
            response.setHeader("Progma", "No-cache"); // 禁止缓存,保证每次都是新验证码
            Console.log(lineCaptcha.getCode()); // 控制台输出,便于调试
            // 3. 将图片写入HTTP响应流
            try {
                lineCaptcha.write(response.getOutputStream());
                // 4. 将验证码文本和生成时间存入Session
                session.setAttribute(captchaProperties.getSession().getKey(), lineCaptcha.getCode());
                session.setAttribute(captchaProperties.getSession().getDate(), new Date());
                response.getOutputStream().close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    
        @RequestMapping("/check")
        public Boolean check(String inputCode, HttpSession session){
            // 1. 检查输入是否为空
            if (!StringUtils.hasLength(inputCode)){
                return false;
            }
            // 2. 从Session中取出之前存储的正确信息
            String sa vedCode = (String) session.getAttribute(captchaProperties.getSession().getKey());
            Date sa veDate = (Date) session.getAttribute(captchaProperties.getSession().getDate());
            // 3. 进行比对(忽略大小写)并检查是否过期
            if (inputCode.equalsIgnoreCase(sa vedCode)){
                if (sa veDate != null && System.currentTimeMillis() - sa veDate.getTime() < session_valid_timeout){
                    return true; // 验证通过
                }
            }
            // 4. 任何一步不满足则返回失败
            return false;
        }
    }

    前端代码实现

    前端页面主要负责展示验证码图片、提供输入框,并处理与后端的交互。

    index.html (主页面)

    
    
    
        
        验证码
        
    
    
    

    输入验证码

    success.html (成功页面)

    
    
    
        
        
        验证成功页
    
    
    

    验证成功

    最终运行效果

    启动Spring Boot应用,访问首页,你会看到如下验证码输入界面:

    ja va使用Hutool工具库实现图形验证码

    输入正确的验证码并提交后,页面会跳转到成功提示页:

    ja va使用Hutool工具库实现图形验证码

    至此,一个完整的、带有验证码的Web登录校验流程就搭建完成了。整个过程借助Hutool,后端代码非常简洁,而验证码的生成、存储、比对和过期校验等核心安全逻辑都已涵盖其中。

    本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系bd@zhengruan.com
    作者最新文章
    编程开发 Java
    相关文章 更多
    Yandex官网入口及网页搜索使用方法
    Yandex官网入口及网页搜索使用方法

    Yandex官网入口是https://www.yondex.net/,该平台支持多语言切换、智能搜索匹配、虚拟键盘变更及实时翻译,提供地图、图片、新闻、购物等垂直服务,并具备账户同步、隐私管理、个性化首页和云存储等功能。

    Java单元测试入门:使用JUnit 5编写第一个测试用例
    Java单元测试入门:使用JUnit 5编写第一个测试用例

    面向初学者的JUnit 5实用入门指南。从测试概念、Maven依赖配置,到手把手编写首个单元测试用例及断言验证,助你掌握Java单元测试的核心流程。

    Java变量未初始化报错解析:局部变量与成员变量默认值差异
    Java变量未初始化报错解析:局部变量与成员变量默认值差异

    深入解析Java中局部变量未初始化编译报错与成员变量自动赋予默认值的机制差异,涵盖JVM内存分配、编译期确定性赋值检查与实际排查修复方案。

    Java获取当前时间并格式化输出:DateTimeFormatter与SimpleDateFormat
    Java获取当前时间并格式化输出:DateTimeFormatter与SimpleDateFormat

    详细讲解在Java中获取当前系统时间并进行格式化输出的两种核心方案:基于Java 8全新日期时间API的DateTimeFormatter与传统遗留的SimpleDateFormat,包含完整代码示例、线程安全机制对比及生产选型建议。

    Java中final与static final常量的定义及初始化规则
    Java中final与static final常量的定义及初始化规则

    深入解析Java中final变量与static final常量的定义、内存语义、初始化时机及合法赋值路径,涵盖编译期常量优化与实战避坑指南。

    Java抽象方法与接口方法的区别及选型建议
    Java抽象方法与接口方法的区别及选型建议

    深入对比Java中抽象类抽象方法与接口方法的语法演进、设计意图及运行期差异,并提供清晰的架构选型决策流程与实战范例。

    Java实现HTTP请求与JSON解析的完整代码示例
    Java实现HTTP请求与JSON解析的完整代码示例

    本文提供Java标准库HttpClient发起HTTP GET/POST请求并结合Jackson进行JSON数据反序列化与序列化的完整代码示例与工程实践指南。

    Java递归出现StackOverflowError的原因分析及栈空间优化方案
    Java递归出现StackOverflowError的原因分析及栈空间优化方案

    详细分析Java递归调用出现StackOverflowError的原因,结合代码说明线程栈、栈帧和递归深度之间的关系,并介绍终止条件排查、迭代改写、减少栈帧开销以及通过-Xss调整JVM栈空间的方法。

    Java空指针异常(NPE)的代码排查与修复实例
    Java空指针异常(NPE)的代码排查与修复实例

    针对Java中常见的NullPointerException(NPE),本文从堆栈日志定位、典型代码触发场景、具体修复代码对比到防御体系进行系统讲解,提供实用且易上手的排查与修复方案。

    selenium上传文件教程本地文件路径设置方法
    selenium上传文件教程本地文件路径设置方法

    深入解析Selenium处理文件上传的技术细节,涵盖标准HTML控件的路径直接注入法与非标准控件的系统级模拟方案,提供Windows与Linux环境下的路径设置最佳实践及常见异常排查。

    查看更多
    精品专题 更多
    装机必备
    装机必备

    正软商城装机必备专区,精选办公、浏览器、安全防护、影音播放、压缩解压、设计创作和系统工具等电脑常用正版软件,帮助用户快速完成新电脑软件配置。

    Windows
    Windows

    正软商城Windows软件专区,汇集适用于Windows电脑的办公、设计、安全防护、影音播放、开发工具和系统优化软件,提供软件介绍、系统要求、正版授权及购买下载服务。

    PDF教程
    PDF教程

    正软商城PDF教程频道提供PDF编辑、转换、合并、拆分、压缩及格式处理方法,同时介绍常用PDF软件和工具的使用技巧。

    Mac软件 更多
    讯飞智作 网页版
    讯飞智作 网页版
    Windows/ macOS/ Linux

    讯飞智作是一款基于语音合成技术、虚拟人驱动技术与数字人形象声音构建能力的 AI 数字人音视频创作平台。

    火山引擎 网页版
    火山引擎 网页版
    Windows/ macOS/ Linux

    火山引擎是字节跳动旗下企业级云与AI服务平台。聚焦大模型核心能力,依托字节自研豆包多模态大模型,凭借火山方舟一站式平台,提供模型精调、推理部署、智能应用搭建等全链路服务,结合高性能AI算力,助力各行业快速落地大模型数字化与智能化应用。

    Aperty macOS版
    Aperty macOS版
    macOS

    Aperty 是 Skylum 推出的 AI 人像修图软件,支持自然肤质修饰、瑕疵处理、面部与身体调整、预设及批量同步。

    WINDOWS 更多
    讯飞智作 网页版
    讯飞智作 网页版
    Windows/ macOS/ Linux

    讯飞智作是一款基于语音合成技术、虚拟人驱动技术与数字人形象声音构建能力的 AI 数字人音视频创作平台。

    火山引擎 网页版
    火山引擎 网页版
    Windows/ macOS/ Linux

    火山引擎是字节跳动旗下企业级云与AI服务平台。聚焦大模型核心能力,依托字节自研豆包多模态大模型,凭借火山方舟一站式平台,提供模型精调、推理部署、智能应用搭建等全链路服务,结合高性能AI算力,助力各行业快速落地大模型数字化与智能化应用。

    PixTV 网页版
    PixTV 网页版
    Windows

    PixTV 是一款在浏览器中使用的 AI 视觉内容创作平台,提供图片、视频、音频、文字生成、AI 分镜、局部重绘、提示词反推和无限画布等工具,适合短剧、漫剧、广告及社交媒体内容制作。