SpringBoot业务开发 02、Springboot快速集成验证码【easy-captcha、kaptcha】超好看样式

简介: SpringBoot业务开发 02、Springboot快速集成验证码【easy-captcha、kaptcha】超好看样式

一、Springboot集成easy-kaptcha


1.1、效果展示


使用PostMan来进行测试:



下面是我将获取到的base64编码的验证码进行还原展示,这里提供一个Base64编码还原/转换网站:base64图片在线转换工具


1、算数验证码



2、Gif类型



3、png类型



4、chinese



5、chinese gif



1.2、快速集成


参考资料:验证码生成 EasyCaptcha、EL-ADMIN开源项目


对应demo项目源码:Gitee仓库地址、Github地址



Captcha captcha = xxx;  //获取对应类型的captcha对象
//在easy-captcha中需要关注的比较重要的就是下面三个方法
String value = captcha.text();  //获取验证码的结果内容
String captchaBase64 captcha.toBase64();  //获取验证码图片的base64编码
captcha.out(response.getOutputStream());  //前后端不分离,直接将图片以流的形式返回


正文开始:Springboot版本依赖为2.6.6,步骤1-4你不用额外关注,关注service封装方法即可


1、导入依赖


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


2、编写配置类:EasyCaptchaConfig.java


import com.changlu.springbootcaptcha.easycaptcha.enums.CodeTypeEnum;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
/**
 * @ClassName EasyCaptchaConfig
 * @Author ChangLu
 * @Date 4/12/2022 5:28 PM
 * @Description 验证码控制器
 */
@Data
@ConfigurationProperties(prefix = "easycaptcha")
@Configuration
public class EasyCaptchaConfig {
    /**
     * 验证码配置
     */
    private CodeTypeEnum codeType;
    /**
     * 验证码内容长度
     */
    private int length = 4;
    /**
     * 验证码宽度
     */
    private int width = 111;
    /**
     * 验证码高度
     */
    private int height = 36;
    /**
     * 验证码字体
     */
    private String fontName;
    /**
     * 字体大小
     */
    private int fontSize = 25;
}


对应的yml配置文件:


# easy-captcha配置,有需要的可以自己加,直接默认的也ok
easycaptcha:
  #  验证码类型配置 查看 LoginProperties 类
  code-type: arithmetic


3、定义枚举类,用于创建验证码的类型:CodeTypeEnum.java


/**
 * @ClassName CodeTypeEnum
 * @Author ChangLu
 * @Date 4/12/2022 5:29 PM
 * @Description 验证码类型枚举类
 */
public enum CodeTypeEnum {
    /**
     * 算数
     */
    ARITHMETIC,
    /**
     * 中文
     */
    CHINESE,
    /**
     * 中文闪图
     */
    CHINESE_GIF,
    /**
     * 闪图
     */
    GIF,
    SPEC
}



4、编写验证码生产器:EasyCaptchaProducer.java


import com.changlu.springbootcaptcha.easycaptcha.config.EasyCaptchaConfig;
import com.changlu.springbootcaptcha.easycaptcha.enums.CodeTypeEnum;
import com.wf.captcha.*;
import com.wf.captcha.base.Captcha;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
/**
 * @ClassName EasyCaptchaProducer
 * @Author ChangLu
 * @Date 4/12/2022 5:35 PM
 * @Description 验证码生成器
 */
@Component
public class EasyCaptchaProducer {
    @Autowired
    private EasyCaptchaConfig easyCaptchaConfig;
    /**
     * 自定义选择类型
     */
    public Captcha getCaptcha(CodeTypeEnum codeType){
        easyCaptchaConfig.setCodeType(codeType);
        return switchCaptcha(easyCaptchaConfig);
    }
    /**
     * 获取默认配置captcha
     */
    public Captcha getCaptcha(){
        return switchCaptcha(easyCaptchaConfig);
    }
    private Captcha switchCaptcha(EasyCaptchaConfig config) {
        Captcha captcha;
        switch (config.getCodeType()) {
            case ARITHMETIC:
                // 算术类型 https://gitee.com/whvse/EasyCaptcha
                captcha = new FixedArithmeticCaptcha(config.getWidth(), config.getHeight());
                //固定设置为两位,图片为算数运算表达式
                captcha.setLen(2);
                break;
            case CHINESE:
                captcha = new ChineseCaptcha(config.getWidth(), config.getHeight());
                captcha.setLen(config.getLength());
                break;
            case CHINESE_GIF:
                captcha = new ChineseGifCaptcha(config.getWidth(), config.getHeight());
                captcha.setLen(config.getLength());
                break;
            case GIF:
                captcha = new GifCaptcha(config.getWidth(), config.getHeight());//最后一位是位数
                captcha.setLen(config.getLength());
                break;
            case SPEC:
                captcha = new SpecCaptcha(config.getWidth(), config.getHeight());
                captcha.setLen(config.getLength());
                break;
            default:
                throw new RuntimeException("验证码配置信息错误!正确配置查看 LoginCodeEnum ");
        }
        return captcha;
    }
    static class FixedArithmeticCaptcha extends ArithmeticCaptcha {
        public FixedArithmeticCaptcha(int width, int height) {
            super(width, height);
        }
        @Override
        protected char[] alphas() {
            // 生成随机数字和运算符
            int n1 = num(1, 10), n2 = num(1, 10);
            int opt = num(3);
            // 计算结果
            int res = new int[]{n1 + n2, n1 - n2, n1 * n2}[opt];
            // 转换为字符运算符
            char optChar = "+-x".charAt(opt);
            this.setArithmeticString(String.format("%s%c%s=?", n1, optChar, n2));
            this.chars = String.valueOf(res);
            return chars.toCharArray();
        }
    }
}



5、编写验证码结果集业务层:EasyCaptchaService.java,我已经将你每次要获取的验证码值以及Base64编码封装到一个Map中返回,你可以拿到之后进行自己相应的业务操作。


import com.changlu.springbootcaptcha.easycaptcha.enums.CodeTypeEnum;
import com.changlu.springbootcaptcha.easycaptcha.producer.EasyCaptchaProducer;
import com.wf.captcha.base.Captcha;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.HashMap;
import java.util.Map;
/**
 * @ClassName EasyCaptchaService
 * @Author ChangLu
 * @Date 4/12/2022 6:20 PM
 * @Description easy-captcha业务工具类
 */
@Service
public class EasyCaptchaService {
    @Autowired
    private EasyCaptchaProducer easyCaptchaProducer;
    /**
     * 获取指定类型的验证码结果以及Base64编码值
     * @param codeType 验证码类型
     * @return
     */
    public Map<String,String> getCaptchaValueAndBase64(CodeTypeEnum codeType){
        Captcha captcha = null;
        if (codeType == null){
            captcha = easyCaptchaProducer.getCaptcha();
        }else {
            captcha = easyCaptchaProducer.getCaptcha(codeType);
        }
        //1、获取到结果值
        String captchaValue = captcha.text();
        //对于数学类型的需要进行处理
        if (codeType == null || codeType == CodeTypeEnum.ARITHMETIC) {
            if (captcha.getCharType() - 1 == CodeTypeEnum.ARITHMETIC.ordinal() && captchaValue.contains(".")) {
                captchaValue = captchaValue.split("\\.")[0];
            }
        }
        //2、获取到Base64编码
        String captchaBase64 = captcha.toBase64();
        Map<String,String> result = new HashMap<>(2);
        result.put("code", captchaValue);
        result.put("base64", captchaBase64);
        return result;
    }
}


6、控制器测试类:(若是你要集成到自己项目,只需要关注调用captcha的service方法即可)


import com.changlu.springbootcaptcha.easycaptcha.enums.CodeTypeEnum;
import com.changlu.springbootcaptcha.easycaptcha.service.EasyCaptchaService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.Map;
/**
 * @ClassName CaptchaController
 * @Author ChangLu
 * @Date 4/12/2022 5:44 PM
 * @Description Easy-captcha控制器
 */
@Controller
@RestController
public class EasyCaptchaController {
    @Autowired
    private EasyCaptchaService easyCaptchaService;
    //1、算术类型
    @GetMapping("/captcha1")
    public Map getGifcCaptcha1(){
        return easyCaptchaService.getCaptchaValueAndBase64(null);
    }
    //2、Gif
    @GetMapping("/captcha2")
    public Map getGifcCaptcha2(){
        return easyCaptchaService.getCaptchaValueAndBase64(CodeTypeEnum.GIF);
    }
    //3、png类型
    @GetMapping("/captcha3")
    public Map getGifcCaptcha3(){
        return easyCaptchaService.getCaptchaValueAndBase64(CodeTypeEnum.SPEC);
    }
    //4、chinese文字类型
    @GetMapping("/captcha4")
    public Map getGifcCaptcha4(){
        return easyCaptchaService.getCaptchaValueAndBase64(CodeTypeEnum.CHINESE);
    }
    //4、chinese Gif类型
    @GetMapping("/captcha5")
    public Map getGifcCaptcha5(){
        return easyCaptchaService.getCaptchaValueAndBase64(CodeTypeEnum.CHINESE_GIF);
    }
}


上面控制器是对五种类型的验证码进行测试,我将对应类型验证码获取到的验证码值和验证码Base64编码封装到了一个Map里,你集成到项目只需要调用该service获取到map从中拿值即可,取到的验证码值存在redis中,base64编码值返回给前端即可。


easy-captcha给我们获取的base64编码是自动就加上data:image/png;base64,,我们无需自己添加

最终map结果集如下:


{
    "base64": "data:image/png;base64,xxx",
    "code": "14"
}


二、Springboot集成Kaptcha


2.1、效果展示


有两个类型算数表达式以及字符类型,依旧使用PostMan来进行测试,效果如下:



1、数学算数表达式



2、字符



2.2、快速集成


说明,该Kapcha案例源自RUOYI-VUE开源项目RuoYi-Vue,这里单独建立demo来进行测试


对应demo项目源码:Gitee仓库地址、Github地址



这个配置相对来说就少多了,接下来就来快速集成吧:Springboot版本为2.6.6


1、添加kaptcha依赖


<!--  案例2:katpcha,对应kaptcha目录案例    -->
<dependency>
    <groupId>com.github.penggle</groupId>
    <artifactId>kaptcha</artifactId>
    <version>2.3.2</version>
</dependency>


2、编写验证码文本生成器:KaptchaTextCreator.java


import com.google.code.kaptcha.text.impl.DefaultTextCreator;
import java.util.Random;
/**
 * 验证码文本生成器
 *
 * @author ruoyi
 */
public class KaptchaTextCreator extends DefaultTextCreator
{
    private static final String[] CNUMBERS = "0,1,2,3,4,5,6,7,8,9,10".split(",");
    @Override
    public String getText()
    {
        Integer result = 0;
        Random random = new Random();
        int x = random.nextInt(10);
        int y = random.nextInt(10);
        StringBuilder suChinese = new StringBuilder();
        int randomoperands = (int) Math.round(Math.random() * 2);
        if (randomoperands == 0)
        {
            result = x * y;
            suChinese.append(CNUMBERS[x]);
            suChinese.append("*");
            suChinese.append(CNUMBERS[y]);
        }
        else if (randomoperands == 1)
        {
            if (!(x == 0) && y % x == 0)
            {
                result = y / x;
                suChinese.append(CNUMBERS[y]);
                suChinese.append("/");
                suChinese.append(CNUMBERS[x]);
            }
            else
            {
                result = x + y;
                suChinese.append(CNUMBERS[x]);
                suChinese.append("+");
                suChinese.append(CNUMBERS[y]);
            }
        }
        else if (randomoperands == 2)
        {
            if (x >= y)
            {
                result = x - y;
                suChinese.append(CNUMBERS[x]);
                suChinese.append("-");
                suChinese.append(CNUMBERS[y]);
            }
            else
            {
                result = y - x;
                suChinese.append(CNUMBERS[y]);
                suChinese.append("-");
                suChinese.append(CNUMBERS[x]);
            }
        }
        else
        {
            result = x + y;
            suChinese.append(CNUMBERS[x]);
            suChinese.append("+");
            suChinese.append(CNUMBERS[y]);
        }
        suChinese.append("=?@" + result);
        return suChinese.toString();
    }
}


3、编写Kaptcha配置类:KaptchaConfig.java


注意注意:该类中的生成器是通过.class的方式引入的需要注意下,每个人包不同你需要进行改正一下



import com.google.code.kaptcha.impl.DefaultKaptcha;
import com.google.code.kaptcha.util.Config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.Properties;
import static com.google.code.kaptcha.Constants.*;
/**
 * @ClassName KaptchaConfig
 * @Author ruoyi
 * @Date 3/24/2022 1:12 PM
 * @Description 验证码配置器
 */
@Configuration
public class KaptchaConfig {
    @Bean(name = "captchaProducer")
    public DefaultKaptcha getKaptchaBean()
    {
        DefaultKaptcha defaultKaptcha = new DefaultKaptcha();
        Properties properties = new Properties();
        // 是否有边框 默认为true 我们可以自己设置yes,no
        properties.setProperty(KAPTCHA_BORDER, "yes");
        // 验证码文本字符颜色 默认为Color.BLACK
        properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_COLOR, "black");
        // 验证码图片宽度 默认为200
        properties.setProperty(KAPTCHA_IMAGE_WIDTH, "160");
        // 验证码图片高度 默认为50
        properties.setProperty(KAPTCHA_IMAGE_HEIGHT, "60");
        // 验证码文本字符大小 默认为40
        properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_SIZE, "38");
        // KAPTCHA_SESSION_KEY
        properties.setProperty(KAPTCHA_SESSION_CONFIG_KEY, "kaptchaCode");
        // 验证码文本字符长度 默认为5
        properties.setProperty(KAPTCHA_TEXTPRODUCER_CHAR_LENGTH, "4");
        // 验证码文本字体样式 默认为new Font("Arial", 1, fontSize), new Font("Courier", 1, fontSize)
        properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_NAMES, "Arial,Courier");
        // 图片样式 水纹com.google.code.kaptcha.impl.WaterRipple 鱼眼com.google.code.kaptcha.impl.FishEyeGimpy 阴影com.google.code.kaptcha.impl.ShadowGimpy
        properties.setProperty(KAPTCHA_OBSCURIFICATOR_IMPL, "com.google.code.kaptcha.impl.ShadowGimpy");
        Config config = new Config(properties);
        defaultKaptcha.setConfig(config);
        return defaultKaptcha;
    }
    @Bean(name = "captchaProducerMath")
    public DefaultKaptcha getKaptchaBeanMath()
    {
        DefaultKaptcha defaultKaptcha = new DefaultKaptcha();
        Properties properties = new Properties();
        // 是否有边框 默认为true 我们可以自己设置yes,no
        properties.setProperty(KAPTCHA_BORDER, "yes");
        // 边框颜色 默认为Color.BLACK
        properties.setProperty(KAPTCHA_BORDER_COLOR, "105,179,90");
        // 验证码文本字符颜色 默认为Color.BLACK
        properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_COLOR, "blue");
        // 验证码图片宽度 默认为200
        properties.setProperty(KAPTCHA_IMAGE_WIDTH, "160");
        // 验证码图片高度 默认为50
        properties.setProperty(KAPTCHA_IMAGE_HEIGHT, "60");
        // 验证码文本字符大小 默认为40
        properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_SIZE, "35");
        // KAPTCHA_SESSION_KEY
        properties.setProperty(KAPTCHA_SESSION_CONFIG_KEY, "kaptchaCodeMath");
        // 验证码文本生成器
        properties.setProperty(KAPTCHA_TEXTPRODUCER_IMPL, "com.changlu.springbootcaptcha.kaptcha.config.KaptchaTextCreator");
        // 验证码文本字符间距 默认为2
        properties.setProperty(KAPTCHA_TEXTPRODUCER_CHAR_SPACE, "3");
        // 验证码文本字符长度 默认为5
        properties.setProperty(KAPTCHA_TEXTPRODUCER_CHAR_LENGTH, "6");
        // 验证码文本字体样式 默认为new Font("Arial", 1, fontSize), new Font("Courier", 1, fontSize)
        properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_NAMES, "Arial,Courier");
        // 验证码噪点颜色 默认为Color.BLACK
        properties.setProperty(KAPTCHA_NOISE_COLOR, "white");
        // 干扰实现类
        properties.setProperty(KAPTCHA_NOISE_IMPL, "com.google.code.kaptcha.impl.NoNoise");
        // 图片样式 水纹com.google.code.kaptcha.impl.WaterRipple 鱼眼com.google.code.kaptcha.impl.FishEyeGimpy 阴影com.google.code.kaptcha.impl.ShadowGimpy
        properties.setProperty(KAPTCHA_OBSCURIFICATOR_IMPL, "com.google.code.kaptcha.impl.ShadowGimpy");
        Config config = new Config(properties);
        defaultKaptcha.setConfig(config);
        return defaultKaptcha;
    }
}



4、编写控制器,KaptchaController.java:来进行两个样式的测试,两个样式在创建时稍微有些不一样,最终都是获取的Base64编码


import com.google.code.kaptcha.Producer;
import org.apache.tomcat.util.codec.binary.Base64;
import org.springframework.util.FastByteArrayOutputStream;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.util.HashMap;
import java.util.Map;
/**
 * @ClassName KaptchaController
 * @Author ChangLu
 * @Date 4/12/2022 7:13 PM
 * @Description Kaptcha控制器
 */
@RestController
@RequestMapping("/kaptcha")
public class KaptchaController {
    @Resource(name = "captchaProducerMath")
    private Producer captchaProducerMath;
    /**
     * 1、获取算数表达式验证码
     * @return
     * @throws Exception
     */
    @GetMapping("/captcha1")
    public Map<String,String> mathKaptcha() throws Exception{
        //1、生成验证码
        String code = captchaProducerMath.createText();
        String capStr = code.substring(0, code.lastIndexOf("@"));
        code = code.substring(code.lastIndexOf("@") + 1);
        //2、获取Base64编码
        BufferedImage bi = captchaProducerMath.createImage(capStr);
        FastByteArrayOutputStream fbaos = new FastByteArrayOutputStream();
        ImageIO.write(bi, "png", fbaos);
        String kaptchaBase64 = Base64.encodeBase64String(fbaos.toByteArray());
        //3、返回结果集
        Map<String,String> result = new HashMap<>(2);
        result.put("code", code);
        result.put("base64", "data:image/png;base64," + kaptchaBase64);
        return result;
    }
    @Resource(name = "captchaProducer")
    private Producer captchaProducer;
    /**
     * 2、获取字符验证码
     * @return
     * @throws Exception
     */
    @GetMapping("/captcha2")
    public Map<String,String> charKaptcha() throws Exception{
        //1、生成验证码(这里就简单些)
        String capStr = null, code = null;
        capStr = code = captchaProducer.createText();
        //2、获取Base64编码
        BufferedImage bi = captchaProducer.createImage(capStr);
        FastByteArrayOutputStream fbaos = new FastByteArrayOutputStream();
        ImageIO.write(bi, "png", fbaos);
        String kaptchaBase64 = Base64.encodeBase64String(fbaos.toByteArray());
        //3、返回结果集
        Map<String,String> result = new HashMap<>(2);
        result.put("code", code);
        result.put("base64", "data:image/png;base64," + kaptchaBase64);
        return result;
    }
}



现在就可以进行测试了,测试效果如2.1所示。

相关文章
|
11天前
|
监控 Java Nacos
使用Spring Boot集成Nacos
通过上述步骤,Spring Boot应用可以成功集成Nacos,利用Nacos的服务发现和配置管理功能来提升微服务架构的灵活性和可维护性。通过这种集成,开发者可以更高效地管理和部署微服务。
103 17
|
11天前
|
XML JavaScript Java
SpringBoot集成Shiro权限+Jwt认证
本文主要描述如何快速基于SpringBoot 2.5.X版本集成Shiro+JWT框架,让大家快速实现无状态登陆和接口权限认证主体框架,具体业务细节未实现,大家按照实际项目补充。
60 11
|
13天前
|
缓存 安全 Java
Spring Boot 3 集成 Spring Security + JWT
本文详细介绍了如何使用Spring Boot 3和Spring Security集成JWT,实现前后端分离的安全认证概述了从入门到引入数据库,再到使用JWT的完整流程。列举了项目中用到的关键依赖,如MyBatis-Plus、Hutool等。简要提及了系统配置表、部门表、字典表等表结构。使用Hutool-jwt工具类进行JWT校验。配置忽略路径、禁用CSRF、添加JWT校验过滤器等。实现登录接口,返回token等信息。
189 12
|
19天前
|
存储 安全 Java
Spring Boot 3 集成Spring AOP实现系统日志记录
本文介绍了如何在Spring Boot 3中集成Spring AOP实现系统日志记录功能。通过定义`SysLog`注解和配置相应的AOP切面,可以在方法执行前后自动记录日志信息,包括操作的开始时间、结束时间、请求参数、返回结果、异常信息等,并将这些信息保存到数据库中。此外,还使用了`ThreadLocal`变量来存储每个线程独立的日志数据,确保线程安全。文中还展示了项目实战中的部分代码片段,以及基于Spring Boot 3 + Vue 3构建的快速开发框架的简介与内置功能列表。此框架结合了当前主流技术栈,提供了用户管理、权限控制、接口文档自动生成等多项实用特性。
71 8
|
1月前
|
XML Java API
Spring Boot集成MinIO
本文介绍了如何在Spring Boot项目中集成MinIO,一个高性能的分布式对象存储服务。主要步骤包括:引入MinIO依赖、配置MinIO属性、创建MinIO配置类和服务类、使用服务类实现文件上传和下载功能,以及运行应用进行测试。通过这些步骤,可以轻松地在项目中使用MinIO的对象存储功能。
107 5
|
3月前
|
Java Maven Docker
gitlab-ci 集成 k3s 部署spring boot 应用
gitlab-ci 集成 k3s 部署spring boot 应用
|
2月前
|
消息中间件 监控 Java
您是否已集成 Spring Boot 与 ActiveMQ?
您是否已集成 Spring Boot 与 ActiveMQ?
67 0
|
6月前
|
监控 druid Java
spring boot 集成配置阿里 Druid监控配置
spring boot 集成配置阿里 Druid监控配置
342 6
|
6月前
|
Java 关系型数据库 MySQL
如何实现Springboot+camunda+mysql的集成
【7月更文挑战第2天】集成Spring Boot、Camunda和MySQL的简要步骤: 1. 初始化Spring Boot项目,添加Camunda和MySQL驱动依赖。 2. 配置`application.properties`,包括数据库URL、用户名和密码。 3. 设置Camunda引擎属性,指定数据源。 4. 引入流程定义文件(如`.bpmn`)。 5. 创建服务处理流程操作,创建控制器接收请求。 6. Camunda自动在数据库创建表结构。 7. 启动应用,测试流程启动,如通过服务和控制器开始流程实例。 示例代码包括服务类启动流程实例及控制器接口。实际集成需按业务需求调整。
477 4
|
6月前
|
消息中间件 Java 测试技术
【RocketMQ系列八】SpringBoot集成RocketMQ-实现普通消息和事务消息
【RocketMQ系列八】SpringBoot集成RocketMQ-实现普通消息和事务消息
445 1

热门文章

最新文章