java:实现简单的验证码功能

news/2024/9/25 21:24:38/

效果

在这里插入图片描述

实现思路

验证码图片的url由后端的一个Controller生成,前端请求这个Controller接口的时候根据当前时间生成一个uuid,并把这个uuid在前端使用localStorage缓存起来,下一次还是从缓存中获取。
在这里插入图片描述
Controller生成验证码之后,把前端传过来的uuid通过redis缓存起来,这里分两次缓存

  • 缓存uuid
  • 以uuid为key,缓存验证码

这样,当点击登录按钮将数据提交到后台登录接口时,会从redis中获取uuid,然后通过这个uuid去获取验证码,和前端用户输入的验证码进行比较。
在这里插入图片描述
在这里插入图片描述

简单验证码

生成随机字符(如数字、字母)的字符串,并将这些字符绘制到一张图片上,最后输出这张图片。

java">import javax.imageio.ImageIO;  
import java.awt.*;  
import java.awt.image.BufferedImage;  
import java.io.File;  
import java.io.IOException;  
import java.util.Random;  public class CaptchaGenerator {  private static final int WIDTH = 100;  private static final int HEIGHT = 40;  private static final Random RANDOM = new Random();  public static void main(String[] args) {  // 生成验证码文本  String captchaText = generateCaptchaText(6);  // 生成验证码图片  File outputFile = new File("captcha.png");  generateCaptchaImage(captchaText, outputFile);  System.out.println("Captcha generated: " + captchaText);  }  private static String generateCaptchaText(int length) {  StringBuilder sb = new StringBuilder(length);  for (int i = 0; i < length; i++) {  // 随机选择字符类型  int type = RANDOM.nextInt(3);  if (type == 0) { // 数字  sb.append(RANDOM.nextInt(10));  } else if (type == 1) { // 小写字母  sb.append((char) ('a' + RANDOM.nextInt(26)));  } else { // 大写字母  sb.append((char) ('A' + RANDOM.nextInt(26)));  }  }  return sb.toString();  }  private static void generateCaptchaImage(String captchaText, File outputFile) {  BufferedImage bufferedImage = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);  Graphics2D g2d = bufferedImage.createGraphics();  // 设置背景色  g2d.setColor(Color.WHITE);  g2d.fillRect(0, 0, WIDTH, HEIGHT);  // 设置字体  Font font = new Font("Arial", Font.BOLD, 24);  g2d.setFont(font);  // 绘制验证码文本  g2d.setColor(Color.BLACK);  FontMetrics fontMetrics = g2d.getFontMetrics();  int x = (WIDTH - fontMetrics.stringWidth(captchaText)) / 2;  int y = ((HEIGHT - fontMetrics.getHeight()) / 2) + fontMetrics.getAscent();  g2d.drawString(captchaText, x, y);  // 释放资源  g2d.dispose();  // 输出图片  try {  ImageIO.write(bufferedImage, "png", outputFile);  } catch (IOException e) {  e.printStackTrace();  }  }  
}

工具包

  • Hutool:是一个多功能的工具包,其中有验证码的功能hutool-captcha
  • easy-captcha:专注验证码

Hutool demo

1、添加依赖

<dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>5.7.16</version>
</dependency>

2、写一个控制器

java">package com.zhangyu.controller;import cn.hutool.captcha.CaptchaUtil;
import cn.hutool.captcha.LineCaptcha;
import cn.hutool.json.JSONObject;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;@RestController
public class CaptchaController {@GetMapping("/captcha")public Map captcha(HttpServletRequest request, HttpServletResponse response) throws IOException {// 生成验证码图片  LineCaptcha lineCaptcha = CaptchaUtil.createLineCaptcha(200, 100, 4, 4);// 获取验证码图片上的文字String captchaText = lineCaptcha.getCode();// 将验证码文字放入session,键名为  CAPTCHA_KEYrequest.getSession().setAttribute("CAPTCHA_KEY", captchaText);System.out.println("文字是" + captchaText);// 输出图片  BufferedImage image = lineCaptcha.getImage();// 图片转base64String base = ImageToBase64.convertImageToBase64(image);System.out.println("base文字是" + base);// 组装数据Map resultMap = new HashMap();resultMap.put("code", captchaText);resultMap.put("img", "data:image/png;base64," + base);return resultMap;}@PostMapping("/submit")public String submit(HttpServletRequest request, @RequestBody JSONObject jsonObject) {String captcha = jsonObject.getStr("captcha");String sessionCaptcha = (String) request.getSession().getAttribute("CAPTCHA_KEY");if (captcha.equalsIgnoreCase(sessionCaptcha)) {return "验证码正确!";} else {return "验证码错误,请重试!";}}
}
java">package com.zhangyu.controller;import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.util.Base64;
import java.io.IOException;public class ImageToBase64 {public static String convertImageToBase64(BufferedImage image) throws IOException {ByteArrayOutputStream baos = new ByteArrayOutputStream();ImageIO.write(image, "png", baos); // 可以改为需要的图片格式,如"jpg"byte[] imageBytes = baos.toByteArray();return Base64.getEncoder().encodeToString(imageBytes);}
}

3、前端测试

这里我用vue写了一个简单的demo

<template><div class="home"><img :src="imgUrl" @click="getCaptchaImg()" alt="captcha" title="点击刷新"><input type="text" name="captcha" placeholder="输入验证码" v-model="text"><button type="submit" @click="submitCaptcha()">提交</button></div>
</template><script>
import baseApi from '@/api/base'
export default {name: 'HomeView',data () {return {imgUrl: '',text: ''}},methods: {async getCaptchaImg() {const res = await baseApi.getCaptchaImg()this.imgUrl = res.img},async submitCaptcha() {const params = {captcha: this.text,}const res = await baseApi.submitCaptcha(params)}},async mounted () {this.getCaptchaImg()}
}
</script>
import ajax from '@/libs/ajax'const baseApi = {getCaptchaImg: () => ajax.request({url: '/captcha',method: 'get'}),submitCaptcha: (data) => ajax.request({url: '/submit',method: 'post',data})
}
export default baseApi
devServer: {port: 9001,open: false,// 配置跨域请求头,解决开发环境的跨域问题headers: {'Access-Control-Allow-Origin': '*',},proxy: 'http://192.168.18.21:9090/'
},

4、效果
在这里插入图片描述
在这里插入图片描述

总结

这里只是用Hutool工具包做了一个demo,easy-captcha我就不展示了也差不多。

真实的场景是返回给前端base64图片和一个uuid,并不是我这里展示的图片文字,然后提交的时候前端把uuid和输入内容传递给后端,由于我这里只是demo所以没有牵扯uuid


http://www.ppmy.cn/news/1510424.html

相关文章

C# 一个队列两个线程,一个线程入,一个线程出,数据不一致的原因

在 C# 中&#xff0c;如果你使用一个队列&#xff0c;并且有两个线程分别进行入队和出队操作&#xff0c;可能会遇到数据不一致的问题。这种问题通常是由于并发访问共享资源&#xff08;即队列&#xff09;时没有进行适当的同步引起的。 目录 问题的原因 解决方案 1. 使用线…

fastzdp_sqlmodel 基于SQLModel封装的专用于FastAPI处理MySQL数据库业务的框架

fastzdp_sqlmodel 基于SQLModel封装的专用于FastAPI处理MySQL数据库业务的框架 Github开源地址&#xff1a;https://github.com/zhangdapeng520/fastzdp_sqlmodel 安装 pip install fastzdp_sqlmodel使用教程 创建表 from typing import Optional from sqlmodel import F…

【网格图dp】力扣931. 下降路径最小和

给你一个 n x n 的 方形 整数数组 matrix &#xff0c;请你找出并返回通过 matrix 的下降路径 的 最小和 。 下降路径 可以从第一行中的任何元素开始&#xff0c;并从每一行中选择一个元素。在下一行选择的元素和当前行所选元素最多相隔一列&#xff08;即位于正下方或者沿对角…

鸿蒙开发Location Kit(位置服务)如何设置

鸿蒙Location Kit 是一个强大的位置服务工具包&#xff0c;允许开发者在应用程序中集成精确的定位功能。Location Kit 提供了多种定位模式&#xff0c;支持室内和室外定位&#xff0c;并结合了GPS、Wi-Fi、蓝牙和基站等多种定位技术。 核心功能 精确定位&#xff1a;支持高精…

AI+仿真,助力工业智能化变革:面向仿真工程师的机器学习工具

仿真AI &#xff1f; 企业的仿真工程师大部分时间都是在面对相似的模型。例如空调管路CFD&#xff0c;汽车保险杠CAE的仿真工作&#xff0c;通过DOE设计迭代&#xff0c;不断的优化尺寸参数&#xff0c;产品外形&#xff0c;从而使得管路流动阻力减小&#xff0c;风速均匀性提高…

昂科烧录器支持PAI-IC澎湃微电子的32位微控制器PT32L031K6T6

芯片烧录行业领导者-昂科技术近日发布最新的烧录软件更新及新增支持的芯片型号列表&#xff0c;其中PAI-IC澎湃微电子的32位微控制器PT32L031K6T6已经被昂科的通用烧录平台AP8000所支持。 PT32L031K6T6是基于Cortex-M0内核的一款32位高性能微控制器&#xff0c;支持工作电压 1…

如何制作优秀的年终总结PPT?

制作优秀的年终总结PPT&#xff0c;是每位职场人士在年底时的一项重要任务。 一个优秀的年终总结PPT不仅能够清晰地展示你过去一年的工作成果&#xff0c;还能让领导对你的工作能力和态度留下深刻印象。 下面&#xff0c;我将从几个方面详细讲解如何制作这样的PPT&#xff0c…

AI作画提示词(Prompts)工程:技巧与最佳实践

文章目录 AI作画提示词(Prompts)工程&#xff1a;技巧与最佳实践一、提示词工程概述二、技巧与最佳实践1. 明确和具体的描述2. 使用上下文3. 指定艺术风格4. 使用关键词5. 适当的限制和优先级6. 实验和优化示例提示词 三、结论 AI作画提示词(Prompts)工程&#xff1a;技巧与最佳…