java生成验证码返回前端图片,后端通过redis存储和校验

news2024/9/30 1:31:52

目录

1.导入maven

2.编写config类

3.编写controller

4.验证


1.导入maven

<dependency>
            <groupId>com.github.penggle</groupId>
            <artifactId>kaptcha</artifactId>
            <version>2.3.2</version>
</dependency>

2.编写config类

CaptchaConfig  

这里使用的是:1*2=2 这样的验证形式,因此我配了一个bean名为captchaProducerMath的验证码配置。

光配置不行,我通过属性properties.setProperty设置了生成格式,也就是验证码文本器。

验证码文本器通过重写getText方法定义生成的格式。格式为10以内的+-*/

注意:验证码文本器改成自己的路径

package com.zsp.quartz.config;


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.*;

/**
 * 验证码配置
 */
@Configuration
public class CaptchaConfig
{
    @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.zsp.quartz.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;
    }
}
KaptchaTextCreator验证码文本生成器

继承DefaultTextCreator,覆盖原有的getText()方法

package com.zsp.quartz.config;

import com.google.code.kaptcha.text.impl.DefaultTextCreator;

import java.util.Random;

/**
 * 验证码文本生成器
 */
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.编写controller

package com.zsp.quartz.controller;

import cn.hutool.core.codec.Base64;
import com.google.code.kaptcha.Producer;
import com.zsp.quartz.Exception.CustomException;
import com.zsp.quartz.entity.dto.CaptchaDto;
import com.zsp.quartz.result.Result;
import com.zsp.quartz.service.Constants;
import com.zsp.quartz.util.IdUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.util.FastByteArrayOutputStream;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.IOException;

@RestController
@RequestMapping("/test")
@CrossOrigin
public class TestController {
    @Resource(name = "captchaProducerMath")
    private Producer captchaProducerMath;

    private RedisTemplate<String, String> stringRedisTemplate;


    /**
     * 生成验证码
     */
    @GetMapping("/captchaImage")
    public Result<CaptchaDto> getCode() throws IOException
    {
        // 保存验证码信息
        String uuid =UUID.randomUUID().toString();
        // 存入redis的key
        String verifyKey = Constants.CAPTCHA_CODE_KEY + uuid;

        String capStr = null, code = null;
        BufferedImage image = null;

        // 生成验证码
        // 生成具体的验证码信息 诸如2/2=?@1
        String capText = captchaProducerMath.createText();
        // 以@进行分割获取问题
        capStr = capText.substring(0, capText.lastIndexOf("@"));
        //以@进行分割,获取最终的实际结果
//        存入redis的值
        code = capText.substring(capText.lastIndexOf("@") + 1);
        image = captchaProducerMath.createImage(capStr);

        // 存入缓存   CAPTCHA_EXPIRATION验证码有效期
        stringRedisTemplate.opsForValue().set(verifyKey, code, Constants.CAPTCHA_EXPIRATION, TimeUnit.MINUTES);
        // 转换流base64信息写出
        FastByteArrayOutputStream os = new FastByteArrayOutputStream();
        try
        {
            ImageIO.write(image, "jpg", os);
        }
        catch (IOException e)
        {
            return Result.fail("生成失败",new CaptchaDto());
        }
        CaptchaDto captchaDto = new CaptchaDto();
        captchaDto.setUuid(uuid); // c8a94873-2c18-4199-871a-c6a6bd2b5241
        captchaDto.setImg(Base64.encode(os.toByteArray()));
        return Result.success("生成成功",captchaDto);
    }

    /**
     * 校验验证码
     * @param code 验证码
     * @param uuid 唯一标识
     * @return 结果
     */
     @PostMapping("validateCaptcha")
    public Result validateCaptcha(String code,String uuid){
        // redis的key 前端传来的
        String verifyKey = Constants.CAPTCHA_CODE_KEY + uuid;
        ValueOperations<String, String> valueOperations = stringRedisTemplate.opsForValue();
        String captcha = valueOperations.get(verifyKey);
        stringRedisTemplate.delete(verifyKey);
        if (captcha == null) {
            throw new CustomException("验证码已过期");
        }
        if (!code.equalsIgnoreCase(captcha)) {
            throw new CustomException("验证码不正确");
        }
        return Result.success("验证成功");
    }
}

 /**
     * 验证码 redis key
     */
    public static final String CAPTCHA_CODE_KEY = "captcha_codes:";

4.验证

postman测试生成验证码图片

base64图片要想在浏览器显示,需要前面加上    data:image/gif;base64,

逗号不要忘了

验证码校验,输入结果和uuid

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

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

相关文章

Mac 文件设置默认展示和排列方式

点击 现在默认展示方式是分栏方式&#xff0c;因我我勾选了 点击这里就可以修改 始终以xx打开&#xff0c;这里我选择了图标视图。 有快捷键 commandJ 修改默认配置。

烟雾文字动画效果

效果展示 CSS 知识点 transform 属性运用transform-origin 属性运用烟雾文字实现 整体页面结构布局实现 <section><p class"text">Lorem ipsum dolor sit amet consectetur adipisicing elit. Vero dolorevoluptas incidunt exercitationem. Consecte…

编程初学者的“天然呆”时光

初学编程的时候&#xff0c;仿佛进入了一个全新的世界&#xff0c;兴奋之余难免迷茫。这个过程中&#xff0c;总是伴随着一些令人哭笑不得的“天然呆”瞬间。本文将回溯我刚开始学写代码时的一些愚蠢但难忘的经历&#xff0c;与读者分享那段独特的学习时光。 一、“Hello Worl…

【pv和pvc】

pv和pvc 一、存在原因二、存储卷分类一、emptyDir存储卷二、hostPath存储卷1.在 node01 节点上创建挂载目录2.在 node02 节点上创建挂载目录3.创建 Pod 资源4.访问测试5.删除pod&#xff0c;再重建&#xff0c;验证是否依旧可以访问原来的内容 三、nfs共享存储卷1.在stor01节点…

UE4 Unlua 初使用小记

function M:Construct()print(Hello World)print(self.Va)local mySubsystem UE4.UHMSGameInstanceSubsystemUE4.UKismetSystemLibrary.PrintString(self,"Get Click Msg From UnLua ")end unlua中tick不能调用的问题&#xff1a; 把该类的Event Tick为灰色显示的删…

Maven 构建配置文件

目录 构建配置文件的类型 配置文件激活 配置文件激活实例 1、配置文件激活 2、通过Maven设置激活配置文件 3、通过环境变量激活配置文件 4、通过操作系统激活配置文件 5、通过文件的存在或者缺失激活配置文件 构建配置文件是一系列的配置项的值&#xff0c;可以用来设置…

【面试经典150 | 哈希表】同构字符串

文章目录 写在前面Tag题目来源题目解读解题思路方法一&#xff1a;哈希表 写在最后 写在前面 本专栏专注于分析与讲解【面试经典150】算法&#xff0c;两到三天更新一篇文章&#xff0c;欢迎催更…… 专栏内容以分析题目为主&#xff0c;并附带一些对于本题涉及到的数据结构等内…

配电运维管理系统:电力数字化升级的关键

随着社会的快速发展和电力需求的增长&#xff0c;配电系统面临着越来越大的压力。为了确保电力供应的稳定性和可靠性&#xff0c;电力企业需要采用先进的管理系统&#xff0c;以提高配电运维的效率和质量。 一、配电运维管理系统的价值 配电运维管理系统通过集成了人工智能…

Nessus安装与使用_nessus安装使用教程

前言&#xff1a; Nessus号称是世界上最流行的漏洞扫描程序&#xff0c;全世界有超过75000个组织在使用它。该工具提供完整的电脑漏洞扫描服务&#xff0c;并随时更新其漏洞数据库。Nessus不同于传统的漏洞扫描软件&#xff0c;Nessus可同时在本机或远端上遥控&#xff0c;进行…

用jad反编译工具查看java接口相关的默认修饰符

接口抽象类复习 -> 默认修饰符是啥 -> jad反编译证明 https://www.cnblogs.com/changrunwei/p/6618117.html 文章目录 背景操作过程反编译前后对比操作截图结论 背景 今天刷到这篇文章&#xff0c;想起之前笔试题总是记不清&#xff0c;所以想证明下。 之前一直不清楚要…

d3dx9_39.dll如何修复?最新修复d3dx9_39.dll方法分享

大家好&#xff01;今天我要和大家分享的主题是“d3dx9_39.dll丢失的修复方法”。我们都知道&#xff0c;在使用电脑的过程中&#xff0c;经常会遇到各种问题&#xff0c;而其中最常见的就是文件丢失。d3dx9_39.dll就是其中一个常见的丢失文件。那么&#xff0c;如何修复这个丢…

Linux|软件安装包deb打包

参考&#xff1a; Ubuntu下的deb打包、安装与卸载 ubuntu打包软件 【Ubuntu】打包C程序及导出依赖库lib 文章目录 导出可执行程序依赖库安装打包工具创建工作目录设定安装的路径编写控制文件使用 dpkg 命令构建 deb包安装 deb包卸载deb包 导出可执行程序依赖库 在.out文件所在…

如何选择适合的Java服务器租用方案

随着共享经济的兴起&#xff0c;租车软件在如今的市场上变得越来越流行。但是&#xff0c;对于许多初创公司和开发者来说&#xff0c;了解开发一个租车软件所需的费用以及如何选择适合的Java服务器租用方案可能是一个挑战。本文将为您提供一些建议&#xff0c;以帮助您了解开发…

攻防世界题目练习——Web引导模式(一)

题目目录 1. command_execution2.xff_referer3.simple_js4.php_rce5.Web_php_include6.upload17. warmup 难度1全部写过了&#xff0c;这个系列里没有 指路&#xff1a; 攻防世界题目练习——Web难度1&#xff08;一&#xff09; 攻防世界题目练习——Web难度1&#xff08;二&a…

软件工程概论

文章目录 软件的定义软件的特点软件的种类软件工程的起源软件工程的三个阶段软件工程概念的提出软件开发的本质软件工程框架软件工程的目标软件工程的原则软件工程的活动 软件的定义 计算机系统中的程序及其文档。 程序是计算任务的处理对象和处理规则的描述&#xff1b; 文档…

Unity 引擎变身收费大亨,程序员们的钱包开始减肥计划

变天了&#xff01;Unity 引擎自 2024 年元旦起&#xff0c;要开始对我们开发者“开刀”了。别急&#xff0c;先听我慢慢道来这个悲欢离合的故事。 Unity 收费新政&#xff1a;别再白嫖了&#xff01; 喜大普奔&#xff01;Unity 引擎宣布从 2024 年 1 月 1 日开始&#xff0…

基于若依ruoyi-nbcio支持flowable流程分类里增加流程应用类型

主要考虑到流程分很多种&#xff0c;普通的是OA流程&#xff0c;还有自定义业务流程&#xff0c;钉钉流程等&#xff0c;所以这里加了一个appType的应用类型&#xff0c;以便后续对不同的应用流程做不同的处理。 1、首先增加一个字典wf_app_type的流程应用类型如下 2、先增加三…

【排序算法】插入排序

文章目录 一&#xff1a;基本概念1.1 介绍1.2 原理1.3 插入排序法思想 二&#xff1a;代码实现2.1 源码2.2 执行结果2.3 测试八万条数据 三&#xff1a;算法分析3.1 时间复杂度3.2 空间复杂度3.3 稳定性 一&#xff1a;基本概念 1.1 介绍 插入式排序属于内部排序法&#xff0…

计算机视觉简介(1)

任何计算机视觉处理流程都始于成像系统&#xff0c;它从景物中捕获反射出来的光线&#xff0c;并将光信号转换成计算机可以读取和处理的图像格式 在计算机成像技术发展的早期&#xff0c;图像通过把胶卷或印刷图像素 化后获得&#xff1b;而现在图 像通常直接由数码相机获取&a…

内网穿透的应用-本地部署Stackedit Markdown编辑器公网远程访问

文章目录 1. docker部署Stackedit2. 本地访问3. Linux 安装cpolar4. 配置Stackedit公网访问地址5. 公网远程访问Stackedit6. 固定Stackedit公网地址 StackEdit是一个受欢迎的Markdown编辑器&#xff0c;在GitHub上拥有20.7k Star&#xff01;&#xff0c;它支持将Markdown笔记保…