当前位置: 首页 > article >正文

springboot使用hutool captcha +vue实现图形验证码

一、效果

使用hutool captcha实现简单的图形验证码,可以参考官网概述 | Hutool

 二、实现步骤

1、导入依赖

 <!--hutool包-->
<dependency>
    <groupId>cn.hutool</groupId>
    <artifactId>hutool-all</artifactId>
    <version>5.8.16</version>
</dependency>

2、后端代码

@RestController
@RequestMapping()
public class CaptchaController {

    private static final String REDIS_KEY = "captcha";

    @Autowired
    private RedisTemplate redisTemplate;

    @GetMapping("/lineCaptcha")
    public Result createLineCaptcha() {
        //创建一个线性验证码图片,并将其输出到浏览器
        LineCaptcha lineCaptcha = CaptchaUtil.createLineCaptcha(100, 40, 4, 9);
        //设置验证码内容,并输出到浏览器
        String code = lineCaptcha.getCode();
        //redis存储验证码内容
        //设置验证码有效期为1分钟
        redisTemplate.opsForValue().set(REDIS_KEY, code, 60, TimeUnit.SECONDS);
        //获取验证码图片的Base64编码数据
        String imageBase64Data = lineCaptcha.getImageBase64Data();
//        // 设置正确的 MIME 类型
//        response.setContentType("image/png");
//        lineCaptcha.write(response.getOutputStream());
//        //将验证码内容保存到响应头中,供客户端验证使用
//        response.setHeader("REDIS_KEY", code);
        return Result.success(imageBase64Data);
    }

    @GetMapping("/circleCaptcha")
    public Result createCircleCaptcha() {

        CircleCaptcha circleCaptcha = CaptchaUtil.createCircleCaptcha(100, 40, 4, 9);

        String code = circleCaptcha.getCode();
        //redis存储验证码内容
        //设置验证码有效期为1分钟
        redisTemplate.opsForValue().set(REDIS_KEY, code, 60, TimeUnit.SECONDS);
        //获取验证码图片的Base64编码数据
        String imageBase64Data = circleCaptcha.getImageBase64Data();

        return Result.success(imageBase64Data);
    }

    @GetMapping("/shearCaptcha")
    public Result createShearCaptcha() {

        ShearCaptcha shearCaptcha = CaptchaUtil.createShearCaptcha(100, 40, 4, 9);

        String code = shearCaptcha.getCode();
        //redis存储验证码内容
        //设置验证码有效期为1分钟
        redisTemplate.opsForValue().set(REDIS_KEY, code, 60, TimeUnit.SECONDS);
        //获取验证码图片的Base64编码数据
        String imageBase64Data = shearCaptcha.getImageBase64Data();

        return Result.success(imageBase64Data);
    }

    @GetMapping("/gifCaptcha")
    public Result createGifCaptcha() {

        GifCaptcha gifCaptcha = CaptchaUtil.createGifCaptcha(100, 40, 4);
        //redis存储验证码内容
        String code = gifCaptcha.getCode();
        //设置验证码有效期为1分钟
        redisTemplate.opsForValue().set(REDIS_KEY, code, 60, TimeUnit.SECONDS);
        //获取验证码图片的Base64编码数据
        String imageBase64Data = gifCaptcha.getImageBase64Data();

        return Result.success(imageBase64Data);
    }

    @GetMapping("/diyCharCaptcha")
    public Result createDiyCharCaptcha() {
        // 定义图形验证码的长、宽、验证码字符数、干扰线宽度
        //ShearCaptcha captcha = CaptchaUtil.createShearCaptcha(100, 40, 4, 4);
        LineCaptcha captcha = CaptchaUtil.createLineCaptcha(100, 40, 4, 4);
        // 自定义纯数字的验证码(随机4位数字,可重复)
        RandomGenerator randomGenerator = new RandomGenerator("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789", 4);

        // 自定义验证码内容为随机4位字符
        captcha.setGenerator(randomGenerator);
        //redis存储验证码内容
        String code = captcha.getCode();
        System.out.println("随机4位字符验证码:" + code);
        String imageBase64Data = captcha.getImageBase64Data();

        return Result.success(imageBase64Data);
    }

    @GetMapping("/diyComputeCaptcha")
    public Result createDiyComputeCaptcha() {
        // 定义图形验证码的长、宽、验证码字符数、干扰线宽度
        LineCaptcha captcha = CaptchaUtil.createLineCaptcha(100, 40, 4, 4);

       
        /**
         *   自定义验证码内容为四则运算方式
         *   numberLength默认为2,即生成的计算式为两个两位数的计算 88+11=
         */
        MathGenerator mathGenerator = new MathGenerator(1);
        
        captcha.setGenerator(mathGenerator);

        //redis存储验证码内容
        String code = captcha.getCode();
        System.out.println("四则运算验证码:" + code);
        // 验证用户输入是否正确
        String userInputCode = "10";
        boolean isCorrect = mathGenerator.verify(code, userInputCode);
        System.out.println("用户输入:" + userInputCode + ",是否正确:" + isCorrect);
        String imageBase64Data = captcha.getImageBase64Data();

        return Result.success(imageBase64Data);
    }
}

 3、前端代码


api

import request from "@/utils/request";

/**
 * 获取验证码
 *
 * @returns 验证码图片
 */
export const getLineCaptcha = () => {
  return request({
    url: "/lineCaptcha",
    method: "get",
    // responseType: "blob",
  });
};
export const getCircleCaptcha = () => {
  return request({
    url: "/circleCaptcha",
    method: "get",
  });
};
export const getShearCaptcha = () => {
  return request({
    url: "/shearCaptcha",
    method: "get",
  });
};
export const getGifCaptcha = () => {
  return request({
    url: "/gifCaptcha",
    method: "get",
  });
};
export const getDiyCharCaptcha = () => {
  return request({
    url: "/diyCharCaptcha",
    method: "get",
  });
};
export const getDiyComputeCaptcha = () => {
  return request({
    url: "/diyComputeCaptcha",
    method: "get",
  });
};

vue页面

<template>
  <div class="captcha">
    <h1>验证码</h1>
    <div class="hutoll">
      <h3>hutool工具</h3>
      <span>
        LineCaptcha:
        <img :src="LineCaptcha" alt="验证码" @click="changeCaptchaImg('Line')"
      /></span>
      <span>
        CircleCaptcha:
        <img
          :src="CircleCaptcha"
          alt="验证码"
          @click="changeCaptchaImg('Circle')"
      /></span>
      <span>
        ShearCaptcha:
        <img
          :src="ShearCaptcha"
          alt="验证码"
          @click="changeCaptchaImg('Shear')"
      /></span>
      <span>
        GifCaptcha:
        <img :src="GifCaptcha" alt="验证码" @click="changeCaptchaImg('Gif')"
      /></span>
      <span>
        DiyCharCaptcha:
        <img
          :src="DiyCharCaptcha"
          alt="验证码"
          @click="changeCaptchaImg('DiyChar')"
      /></span>
      <span>
        DiyComputeCaptcha:
        <img
          :src="DiyComputeCaptcha"
          alt="验证码"
          @click="changeCaptchaImg('DiyCompute')"
      /></span>
    </div>
    
  </div>
</template>

<script setup>
import { ref, onMounted, onBeforeUnmount } from "vue";
import {
  getLineCaptcha,
  getCircleCaptcha,
  getShearCaptcha,
  getGifCaptcha,
  getDiyCharCaptcha,
  getDiyComputeCaptcha,

} from "@/api/captcha/index";
import { ElMessage } from "element-plus";

const LineCaptcha = ref("");
const CircleCaptcha = ref("");
const ShearCaptcha = ref("");
const GifCaptcha = ref("");
const DiyCharCaptcha = ref("");
const DiyComputeCaptcha = ref("");


const captchaRefs = {
  Line: LineCaptcha,
  Circle: CircleCaptcha,
  Shear: ShearCaptcha,
  Gif: GifCaptcha,
  DiyChar: DiyCharCaptcha,
  DiyCompute: DiyComputeCaptcha,
 
};

const getCaptcha = async (captchaType) => {
  try {
    let res;
    switch (captchaType) {
      case "Line":
        res = await getLineCaptcha();
        break;
      case "Circle":
        res = await getCircleCaptcha();
        break;
      case "Shear":
        res = await getShearCaptcha();
        break;
      case "Gif":
        res = await getGifCaptcha();
        break;
      case "DiyChar":
        res = await getDiyCharCaptcha();
        break;
      case "DiyCompute":
        res = await getDiyComputeCaptcha();
        break;

      default:
        throw new Error("Invalid captcha type");
    }
    captchaRefs[captchaType].value = res.data;
  } catch (error) {
    console.error(`获取 ${captchaType} 验证码时出错:`, error);
    ElMessage.error(`获取 ${captchaType} 验证码时出错,请稍后再试`);
  }
};

const changeCaptchaImg = async (captchaType) => {
  await getCaptcha(captchaType);
};

const revokeCaptchaUrls = () => {
  for (const captchaType in captchaRefs) {
    if (captchaRefs[captchaType].value) {
      URL.revokeObjectURL(captchaRefs[captchaType].value);
    }
  }
};

onMounted(async () => {
  await Promise.all([
    getCaptcha("Line"),
    getCaptcha("Circle"),
    getCaptcha("Shear"),
    getCaptcha("Gif"),
    getCaptcha("DiyChar"),
    getCaptcha("DiyCompute"),
    
  ]);
});

onBeforeUnmount(() => {
  revokeCaptchaUrls();
});
</script>

<style lang="scss" scoped></style>

http://www.kler.cn/a/467202.html

相关文章:

  • 智能新纪元:代理AI的崛起与未来
  • ArcGIS JSAPI 高级教程 - 通过RenderNode实现视频融合效果(不借助三方工具)
  • 【GeekBand】C++设计模式笔记24_Visitor_访问器
  • 爬虫案例-爬取某度文档
  • 洛谷B4071 [GESP202412 五级] 武器强化
  • Java 数据库连接 - Sqlite
  • 解决openpyxl操纵带公式的excel或者csv之后,pandas无法读取数值的问题
  • 基于PHP+MySQL实现的web端借还书系统
  • android studio老版本下载教程
  • 【AI学习】Transformer深入学习(二):从MHA、MQA、GQA到MLA
  • 阿里云-通义灵码:在 PyCharm 中的强大助力(下)
  • 急需升级,D-Link 路由器漏洞被僵尸网络广泛用于 DDoS 攻击
  • GPIO、RCC库函数
  • 104周六复盘 (188)UI
  • perl包安装的CPAN大坑
  • SQL-【DDL+DML】
  • 30分钟学会HTML
  • vscode下载vetur和vue-helper插件之后删除键(backspace)失效
  • Java十六
  • 【Web】极简快速入门Vue 3