Easy-Captcha验证码 生成以及校验(简单易懂)

news2025/1/11 12:54:08

目录

  • 说明
  • pom引入
  • 详解参数类使用
    • easy-captcha 中提供了下面几种类
    • 源码说明
  • Captcha使用
  • 验证图解
  • 源码测试GitHub

说明

Java图形验证码,支持gif、中文、算术等类型,可用于Java Web、JavaSE等项目

pom引入

	<dependency>
			<groupId>com.github.whvcse</groupId>
			<artifactId>easy-captcha</artifactId>
			<version>1.6.2</version>
		</dependency>

详解参数类使用

easy-captcha 中提供了下面几种类

类名说明图片
ArithmeticCaptcha数字加减乘除验证在这里插入图片描述
ChineseCaptcha中文验证在这里插入图片描述
ChineseGifCaptcha中文动态验证在这里插入图片描述
GifCaptcha动态字符验证在这里插入图片描述
SpecCaptcha字符验证在这里插入图片描述
CaptchaUtil输出类

源码说明

在上面的类中,都是继承自Captcha类,类中提供了两个主要抽象方法,自定义验证码生成器也需继承Captcha,实现下面两个方法。

   public abstract boolean out(OutputStream var1);

    public abstract String toBase64();

来看SpecCaptcha 默认生成验证码的工具类,其他几种验证码生成类,一样的逻辑。

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

package com.wf.captcha;

import com.wf.captcha.base.Captcha;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.OutputStream;
import javax.imageio.ImageIO;

public class SpecCaptcha extends Captcha {
  //空构造方法
  public SpecCaptcha() {
   }
   //设置验证码的长宽
    public SpecCaptcha(int width, int height) {
        this();
        this.setWidth(width);
        this.setHeight(height);
    }
//设置验证码的长宽,和生成验证码的长度
    public SpecCaptcha(int width, int height, int len) {
        this(width, height);
        this.setLen(len);
    }
//设置验证码的长宽,和生成验证码的长度,以及字体
    public SpecCaptcha(int width, int height, int len, Font font) {
        this(width, height, len);
        this.setFont(font);
    }
  // 验证码返回
    public boolean out(OutputStream out) {
        return this.graphicsImage(this.textChar(), out);
    }
//验证码转为base64
    public String toBase64() {
        return this.toBase64("data:image/png;base64,");
    }

//生成验证码逻辑
    private boolean graphicsImage(char[] strs, OutputStream out) {
        try {
            BufferedImage bi = new BufferedImage(this.width, this.height, 1);
            Graphics2D g2d = (Graphics2D)bi.getGraphics();
            g2d.setColor(Color.WHITE);
            g2d.fillRect(0, 0, this.width, this.height);
            g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            this.drawOval(2, g2d);
            g2d.setStroke(new BasicStroke(2.0F, 0, 2));
            this.drawBesselLine(1, g2d);
            g2d.setFont(this.getFont());
            FontMetrics fontMetrics = g2d.getFontMetrics();
            int fW = this.width / strs.length;
            int fSp = (fW - (int)fontMetrics.getStringBounds("W", g2d).getWidth()) / 2;

            for(int i = 0; i < strs.length; ++i) {
                g2d.setColor(this.color());
                int fY = this.height - (this.height - (int)fontMetrics.getStringBounds(String.valueOf(strs[i]), g2d).getHeight() >> 1);
                g2d.drawString(String.valueOf(strs[i]), i * fW + fSp + 3, fY - 3);
            }

            g2d.dispose();
            ImageIO.write(bi, "png", out);
            out.flush();
            boolean var20 = true;
            return var20;
        } catch (IOException var18) {
            var18.printStackTrace();
        } finally {
            try {
                out.close();
            } catch (IOException var17) {
                var17.printStackTrace();
            }

        }

        return false;
    }
}

Captcha使用

以上几种提供的工具类,都有使用测试

package com.test.execption.controller;

import com.ramostear.captcha.HappyCaptcha;
import com.wf.captcha.*;
import com.wf.captcha.utils.CaptchaUtil;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * 类描述:EasyCaptcha 验证码工具
 *
 * @author admin
 * @date 2023-01-02 17:47
 **/

@RestController
@RequestMapping(value = "captcha")
public class EasyCaptchaController {

    /**
     * 生成字符串验证码
     *
     * @param request
     * @param response
     * @return
     */
    @GetMapping(value = "generatorStr")
    public void generator(HttpServletRequest request, HttpServletResponse response) {
        try {
            CaptchaUtil.out(request, response);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }


    /**
     * 生成数字验证码
     *
     * @param request
     * @param response
     * @return
     */
    @GetMapping(value = "generatorNum")
    public void generatorNum(HttpServletRequest request, HttpServletResponse response) {
        try {
            ArithmeticCaptcha arithmeticCaptcha = new ArithmeticCaptcha(200, 250);
            arithmeticCaptcha.setLen(2);
            CaptchaUtil.out(arithmeticCaptcha, request, response);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 生成中文验证码
     *
     * @param request
     * @param response
     * @return
     */
    @GetMapping(value = "generatorChinese")
    public void generatorChinese(HttpServletRequest request, HttpServletResponse response) {
        try {
            ChineseCaptcha chineseCaptcha = new ChineseCaptcha(200, 250);
            chineseCaptcha.setLen(2);
            CaptchaUtil.out(chineseCaptcha, request, response);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 生成中文动态验证码
     *
     * @param request
     * @param response
     * @return
     */
    @GetMapping(value = "generatorChineseGif")
    public void generatorChineseGif(HttpServletRequest request, HttpServletResponse response) {
        try {
            ChineseGifCaptcha chineseGifCaptcha = new ChineseGifCaptcha(200, 250);
            chineseGifCaptcha.setLen(2);
            CaptchaUtil.out(chineseGifCaptcha, request, response);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 生成字符动态验证码
     *
     * @param request
     * @param response
     * @return
     */
    @GetMapping(value = "generatorGif")
    public void generatorGif(HttpServletRequest request, HttpServletResponse response) {
        try {
            GifCaptcha captcha = new GifCaptcha(200, 250);
            captcha.setLen(2);
            CaptchaUtil.out(captcha, request, response);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 生成字符动态验证码
     * 这个为默认验证码生成器
     * @param request
     * @param response
     * @return
     */
    @GetMapping(value = "generatorSpec")
    public void generatorSpec(HttpServletRequest request, HttpServletResponse response) {
        try {
            SpecCaptcha captcha = new SpecCaptcha(200, 250);
            captcha.setLen(2);
            CaptchaUtil.out(captcha, request, response);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }




    /**
     * 验证码校验,并且验证通过后清除,下次不允许再用
     *
     * @param verifyCode
     * @param request
     * @return
     */
    @GetMapping("/verify")
    public String verify(String verifyCode, HttpServletRequest request) {

        Boolean aBoolean = CaptchaUtil.ver(verifyCode, request);
        if (aBoolean) {
            CaptchaUtil.clear(request); //清除验证码
            return "通过";
        }
        return "不通过";
    }

验证图解

使用数字运算验证

生成验证码:
在这里插入图片描述
校验验证码:
结果不对,不通过
在这里插入图片描述
结果正确,通过
在这里插入图片描述

源码测试GitHub

github 测试代码

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

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

相关文章

【C++】 bitset(位图)的使用

目录 一、bitset的基本介绍 1. 位图的概念 2. 位图的应用 二、biset的基本使用 1. bitset的成员函数 2. 基本使用介绍 1. 定义方式 2. 成员函数的使用 一、bitset的基本介绍 1. 位图的概念 所谓位图&#xff0c;就是用每一位来存放某种状态&#xff0c;适用于海量数…

win系统一台电脑安装两个不同版本的mysql教程

1.mysql下载zip包&#xff08;地址&#xff09;MySQL :: Download MySQL Community Serverhttps://dev.mysql.com/downloads/mysql/ 2.解压在你的电脑上&#xff08;不要再C盘和带中文的路径&#xff09; data和my.ini是没有的。 3.创建my.ini文件 创建记事本改变后缀名就可以 …

【5G RRC】小区搜索(Cell Search)和系统捕获(System Acquisition)流程

博主未授权任何人或组织机构转载博主任何原创文章&#xff0c;感谢各位对原创的支持&#xff01; 博主链接 本人就职于国际知名终端厂商&#xff0c;负责modem芯片研发。 在5G早期负责终端数据业务层、核心网相关的开发工作&#xff0c;目前牵头6G算力网络技术标准研究。 博客…

环境变量?拿来把你!

文章目录环境变量直接运行程序的第一种方法&#xff1a;把程序移动到系统目录底下echo $环境变量&#xff1a;查看环境变量PATH:指定命令的搜索路径export 定义一个新的环境变量export PATH旧路径&#xff1a;新路径getenv&#xff1a;获取环境变量—获取环境变量的第一种方式s…

车载诊断协议UDS——读写服务Service 22/2E

在UDS协议中,对于服务常用有两种格式: 1、Service (服务) + Subfunction( 子服务) 子服务可理解为对服务的功能补充,比如会话模式Service 10服务,子服务可以分为不同的会话模式(默认会话模式、扩展会话模式、编程会话模式等等),用来区分服务的执行权限。 2、Servi…

[OC学习笔记]启动流程(objc部分)

先回顾下这张图&#xff0c;回顾下整体流程。现在分析下在此流程中objc4源码&#xff08;818.2&#xff09;的处理逻辑。 _objc_init解析 我们在上图可以看出&#xff0c;dyld在main函数之前&#xff08;pre-main&#xff09;会间接调用到objc的_objc_init&#xff0c;其中使…

洛谷—— AT_abc157_a [ABC157A] Duplex Printing

文章目录[ABC157A] Duplex Printing题面翻译题目描述输入格式输出格式说明提示题目描述输入格式输出格式样例 #1样例输入 #1样例输出 #1样例 #2样例输入 #2样例输出 #2样例 #3样例输入 #3样例输出 #3提示制約Sample Explanation 1AC代码[ABC157A] Duplex Printing 题面翻译 题…

GC调优

GC调优一、新生代调优二、幸存区调优三、老年代调优四、GC调优案例案例一&#xff1a;Full GC和Minor GC频繁案例二&#xff1a;请求高峰期发生Full GC&#xff0c;单次暂停时间特别长&#xff08;CMS&#xff09;案例三&#xff1a;老年代充裕情况下&#xff0c;发生Full GC&a…

SQL中灵活的视图

文章目录视图的创建、嵌套及特性创建视图查询视图视图的嵌套常见的8个使用场景场景一&#xff1a;仅提供需要的数据场景二&#xff1a;对特定的用户仅开放特定的数据&#xff0c;达到保护敏感数据的目的&#xff0c;提升了数据安全性&#xff1b;仅筛选需要的数据场景四&#x…

迭代器模式 实现ES大量数据查询

目录 项目需求 要求 普通策略 升级策略&#xff1a;使用迭代器模式 迭代器模式组成 代码实现 查询实体 返回实体 实现类 代码测试 mock的ES返回结果json数据 第一次返回结果 第二次返回结果 第三次返回结果 postMan请求, 控制台打印结果 项目需求 数据从Mysq…

云计算服务安全指南

声明 本文是学习GB-T 31167-2014 信息安全技术 云计算服务安全指南. 下载地址而整理的学习笔记,分享出来希望更多人受益,如果存在侵权请及时联系我们 云计算服务安全退出服务 9.1退出要求 合同到期或其他原因都可能导致客户退出云计算服务&#xff0c;或将数据和业务系统迁…

植物大战僵尸:代码实现自动收集阳光

通过阳光增加的值为切入点&#xff0c;找到自动收集阳光的关键判断并实现自动收集阳光&#xff0c;首先我们猜测当阳光出现后&#xff0c;我们是否会去点击&#xff0c;这个过程必然是由一个判断和一个时钟周期事件来控制的&#xff0c;那么当我们点击下落的阳光以后&#xff0…

DC-UNet:重新思考UNet架构和双通道高效CNN医学图像

摘要 经典UNet的体系架构在某些方面存在着局限性。因此本文对其结构提出了改进。1)设计高效的CNN架构来取代编码器和解码器;2)在最先进的U-Net模型的基础上&#xff0c;应用残差模块来取代编码器和解码器之间的跳过连接来进行改进。 医学图像分割是通过一些自动和半自动的方法…

linux系统中块设备的基本实现方法

大家好&#xff0c;今天主要和大家聊一聊&#xff0c;如何使用linux系统中的块设备的实现方法。 目录 第一&#xff1a;块设备基本简介 第二&#xff1a;块设备驱动框架 第三&#xff1a;实现程序代码实现 第一&#xff1a;块设备基本简介 块设备驱动与字符设备驱动之间的主…

双指针:环形链表II

题目&#xff1a;142. 环形链表 II 我们知道&#xff0c;判断一个链表是否为环是这样的&#xff1a; public boolean hasCycle(ListNode head) {ListNode slow head,quickly head;while(quickly ! null && quickly.next ! null){slow slow.next;quickly quickly.n…

【javaSE】中异常如何处理

目录 文章目录 一、异常的初识 1.1异常的概念 1.2异常的体系结构 1.3异常的分类 二、异常的处理和抛出 2.1防御式编程 2.2异常的抛出 2.3异常的捕获 2.4异常的处理流程 三、自定义异常类 3.1举例&#xff1a;实现一个用户登录功能 一、异常的初识 1.1异常的概念 在…

Perl语法

Perl从许多语言中借用了语法和概念&#xff1a;awk&#xff0c;sed&#xff0c;C&#xff0c;Bourne Shell&#xff0c;Smalltalk&#xff0c;Lisp甚至是英语。每个简单的语句必须以分号&#xff08;;&#xff09;结尾&#xff0c;和Java类似&#xff0c;与Python不同。 一、扩…

【苹果推群发iMessage推】软件安装它起首将消息发送到Apple Push服务器,而后Apple Push服务器将消息发送到装配了应用程序的手机

推荐内容IMESSGAE相关 作者推荐内容iMessage苹果推软件 *** 点击即可查看作者要求内容信息作者推荐内容1.家庭推内容 *** 点击即可查看作者要求内容信息作者推荐内容2.相册推 *** 点击即可查看作者要求内容信息作者推荐内容3.日历推 *** 点击即可查看作者要求内容信息作者推荐…

《小猫猫大课堂》——数组,操作符,常见关键字

更新不易&#xff0c;麻烦多多点赞&#xff0c;欢迎你的提问&#xff0c;感谢你的转发&#xff0c; 最后的最后&#xff0c;关注我&#xff0c;关注我&#xff0c;关注我&#xff0c;你会看到更多有趣的博客哦&#xff01;&#xff01;&#xff01; 喵喵喵&#xff0c;你对我…

Java--方法重写

1&#xff09;概念 重写(override)&#xff1a;也称为覆盖。重写是子类对父类非静态、非private修饰&#xff0c;非final修饰&#xff0c;非构造方法等的实现过程 进行重新编写, 返回值和形参都不能改变。即外壳不变&#xff0c;核心重写&#xff01;重写的好处在于子类可以根据…