Spring Boot工程集成验证码生成与验证功能教程

🌟 前言

欢迎来到我的技术小宇宙!🌌 这里不仅是我记录技术点滴的后花园,也是我分享学习心得和项目经验的乐园。📚 无论你是技术小白还是资深大牛,这里总有一些内容能触动你的好奇心。🔍

🤖 洛可可白:个人主页

🔥 个人专栏:✅前端技术 ✅后端技术

🏠 个人博客:洛可可白博客

🐱 代码获取:bestwishes0203

📷 封面壁纸:洛可可白wallpaper


CDDN

文章目录

  • Spring Boot工程集成验证码生成与验证功能教程
    • 1. 创建验证码工具类
    • 2. 控制层实现
    • 3. 客户端展示验证码
    • 4. 验证验证码
    • 📌 联系方式
    • 🚀 获取源代码
    • 🎉 结语

Spring Boot工程集成验证码生成与验证功能教程

验证码是一种常见的安全机制,用于防止自动化工具(如爬虫)对网站进行恶意操作。在Web应用中,验证码通常以图像的形式出现,要求用户输入图像中显示的字符。本文将介绍如何在Spring Boot工程中实现一个随机生成验证码的功能。

1. 创建验证码工具类

首先,我们需要创建一个工具类VerifyCodeUtils,用于生成随机验证码并输出为图像。

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Arrays;
import java.util.Random;public class VerifyCodeUtils {//使用到Algerian字体,系统里没有的话需要安装字体,字体只显示大写,去掉了1,0,i,o几个容易混淆的字符public static final String VERIFY_CODES = "23456789ABCDEFGHJKLMNPQRSTUVWXYZ";private static Random random = new Random();/*** 使用系统默认字符源生成验证码** @param verifySize 验证码长度* @return*/public static String generateVerifyCode(int verifySize) {return generateVerifyCode(verifySize, VERIFY_CODES);}/*** 使用指定源生成验证码** @param verifySize 验证码长度* @param sources    验证码字符源* @return*/public static String generateVerifyCode(int verifySize, String sources) {if (sources == null || sources.length() == 0) {sources = VERIFY_CODES;}int codesLen = sources.length();Random rand = new Random(System.currentTimeMillis());StringBuilder verifyCode = new StringBuilder(verifySize);for (int i = 0; i < verifySize; i++) {verifyCode.append(sources.charAt(rand.nextInt(codesLen - 1)));}return verifyCode.toString();}/*** 生成随机验证码文件,并返回验证码值** @param w* @param h* @param outputFile* @param verifySize* @return* @throws IOException*/public static String outputVerifyImage(int w, int h, File outputFile, int verifySize) throws IOException {String verifyCode = generateVerifyCode(verifySize);outputImage(w, h, outputFile, verifyCode);return verifyCode;}/*** 输出随机验证码图片流,并返回验证码值** @param w* @param h* @param os* @param verifySize* @return* @throws IOException*/public static String outputVerifyImage(int w, int h, OutputStream os, int verifySize) throws IOException {String verifyCode = generateVerifyCode(verifySize);outputImage(w, h, os, verifyCode);return verifyCode;}/*** 生成指定验证码图像文件** @param w* @param h* @param outputFile* @param code* @throws IOException*/public static void outputImage(int w, int h, File outputFile, String code) throws IOException {if (outputFile == null) {return;}File dir = outputFile.getParentFile();if (!dir.exists()) {dir.mkdirs();}try {outputFile.createNewFile();FileOutputStream fos = new FileOutputStream(outputFile);outputImage(w, h, fos, code);fos.close();} catch (IOException e) {throw e;}}/*** 输出指定验证码图片流** @param w* @param h* @param os* @param code* @throws IOException*/public static void outputImage(int w, int h, OutputStream os, String code) throws IOException {int verifySize = code.length();BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);Random rand = new Random();Graphics2D g2 = image.createGraphics();g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);Color[] colors = new Color[5];Color[] colorSpaces = new Color[]{Color.WHITE, Color.CYAN,Color.GRAY, Color.LIGHT_GRAY, Color.MAGENTA, Color.ORANGE,Color.PINK, Color.YELLOW};float[] fractions = new float[colors.length];for (int i = 0; i < colors.length; i++) {colors[i] = colorSpaces[rand.nextInt(colorSpaces.length)];fractions[i] = rand.nextFloat();}Arrays.sort(fractions);g2.setColor(Color.GRAY);// 设置边框色g2.fillRect(0, 0, w, h);Color c = getRandColor(200, 250);g2.setColor(c);// 设置背景色g2.fillRect(0, 2, w, h - 4);//绘制干扰线Random random = new Random();g2.setColor(getRandColor(160, 200));// 设置线条的颜色for (int i = 0; i < 20; i++) {int x = random.nextInt(w - 1);int y = random.nextInt(h - 1);int xl = random.nextInt(6) + 1;int yl = random.nextInt(12) + 1;g2.drawLine(x, y, x + xl + 40, y + yl + 20);}// 添加噪点float yawpRate = 0.05f;// 噪声率int area = (int) (yawpRate * w * h);for (int i = 0; i < area; i++) {int x = random.nextInt(w);int y = random.nextInt(h);int rgb = getRandomIntColor();image.setRGB(x, y, rgb);}shear(g2, w, h, c);// 使图片扭曲g2.setColor(getRandColor(100, 160));int fontSize = h - 4;Font font = new Font("Algerian", Font.ITALIC, fontSize);g2.setFont(font);char[] chars = code.toCharArray();for (int i = 0; i < verifySize; i++) {AffineTransform affine = new AffineTransform();affine.setToRotation(Math.PI / 4 * rand.nextDouble() * (rand.nextBoolean() ? 1 : -1), (w / verifySize) * i + fontSize / 2, h / 2);g2.setTransform(affine);g2.drawChars(chars, i, 1, ((w - 10) / verifySize) * i + 5, h / 2 + fontSize / 2 - 10);}g2.dispose();ImageIO.write(image, "jpg", os);}private static Color getRandColor(int fc, int bc) {if (fc > 255)fc = 255;if (bc > 255)bc = 255;int r = fc + random.nextInt(bc - fc);int g = fc + random.nextInt(bc - fc);int b = fc + random.nextInt(bc - fc);return new Color(r, g, b);}private static int getRandomIntColor() {int[] rgb = getRandomRgb();int color = 0;for (int c : rgb) {color = color << 8;color = color | c;}return color;}private static int[] getRandomRgb() {int[] rgb = new int[3];for (int i = 0; i < 3; i++) {rgb[i] = random.nextInt(255);}return rgb;}private static void shear(Graphics g, int w1, int h1, Color color) {shearX(g, w1, h1, color);shearY(g, w1, h1, color);}private static void shearX(Graphics g, int w1, int h1, Color color) {int period = random.nextInt(2);boolean borderGap = true;int frames = 1;int phase = random.nextInt(2);for (int i = 0; i < h1; i++) {double d = (double) (period >> 1)* Math.sin((double) i / (double) period+ (6.2831853071795862D * (double) phase)/ (double) frames);g.copyArea(0, i, w1, 1, (int) d, 0);if (borderGap) {g.setColor(color);g.drawLine((int) d, i, 0, i);g.drawLine((int) d + w1, i, w1, i);}}}private static void shearY(Graphics g, int w1, int h1, Color color) {int period = random.nextInt(40) + 10; // 50;boolean borderGap = true;int frames = 20;int phase = 7;for (int i = 0; i < w1; i++) {double d = (double) (period >> 1)* Math.sin((double) i / (double) period+ (6.2831853071795862D * (double) phase)/ (double) frames);g.copyArea(i, 0, 1, h1, 0, (int) d);if (borderGap) {g.setColor(color);g.drawLine(i, (int) d, i, 0);g.drawLine(i, (int) d + h1, i, h1);}}}
}

2. 控制层实现

在Spring Boot的控制器中,我们需要提供一个接口来生成验证码并将其发送给客户端。

// VerifyController.java
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
public class VerifyController {@GetMapping("/generateImageCode")public void generateImageCode(HttpSession session, HttpServletResponse response) throws IOException {//随机生成四位随机数String code = VerifyCodeUtils.generateVerifyCode(4);//保存到session域中session.setAttribute("code", code);//根据随机数生成图片,reqponse响应图片response.setContentType("image/png");ServletOutputStream os = response.getOutputStream();VerifyCodeUtils.outputImage(130, 60, os, code);}
}

3. 客户端展示验证码

在Web页面中,我们需要添加一个图像标签来展示验证码。

<!-- 在HTML中添加验证码图像 -->
<img src="/generateImageCode" alt="验证码" onclick="this.src='/generateImageCode?'+Math.random();" />

4. 验证验证码

在用户提交表单时,我们需要验证用户输入的验证码是否正确。这通常在后端进行,通过比较用户输入的验证码与Session中保存的验证码。

// 在登录方法中验证验证码
@PostMapping("/login")
public ResponseEntity<?> login(@RequestParam String username, @RequestParam String password, HttpSession session) {// 获取用户输入的验证码String userInputCode = request.getParameter("code");// 获取Session中保存的验证码String sessionCode = (String) session.getAttribute("code");// 验证验证码if (!sessionCode.equals(inputCode)) {// 验证码错误return ResponseEntity.status(HttpStatus.BAD_REQUEST).body("验证码错误");}// 验证码正确,继续登录逻辑// ...
}

📌 联系方式

如果您对我们的项目感兴趣,或者有任何技术问题想要探讨,欢迎通过以下方式与我联系。我非常期待与您交流,共同学习,共同进步!🌊💡🤖

  • 邮箱:2109664977@qq.com 📧
  • Gitee:https://gitee.com/bestwishes0203 🐱
  • GitHub:https://github.com/bestwishes0203 🐙
  • CSDN主页:https://blog.csdn.net/interest_ing_/ 📖
  • 个人博客:访问我的博客 🏠

🚀 获取源代码

  • 后端案例:https://gitee.com/bestwishes0203/Front-end-example
  • 前端案例:https://gitee.com/bestwishes0203/Back-end-example

🎉 结语

感谢你的访问,如果你对我的技术文章或项目感兴趣,欢迎通过以上方式与我联系。让我们一起在技术的道路上不断前行!🚀

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

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

相关文章

《Vite 报错》ReferenceError: module is not defined in ES module scope

ReferenceError: module is not defined in ES module scope 解决方案 postcss.config.js 要改为 postcss.config.cjs&#xff0c;也就是 .cjs 后缀。 原因解析 下图提示&#xff0c;packages.json 中的属性 type 设置为 module。所有 *.js 文件现在都被解释为 ESM&#xff…

电商店群系统的搭建需要用到的官方接口如何申请?

电商电子商务企业往往都会需要再很多平台上面铺货&#xff0c;上传商品。 高科技的今天&#xff0c;我们已经不需要手动一个个品去上传了。那通过官方接口&#xff0c;如何实现快速铺货呢&#xff1f; 1688官方开放平台的API接口类型众多&#xff0c;并不是所有的企业都能申请…

GitHub Pages部署静态页面

GitHub Pages是GitHub提供的静态页面托管服务&#xff0c;可以用来托管个人博客、项目文档等静态页面。GitHub Pages支持Jekyll&#xff0c;可以使用Jekyll构建博客&#xff0c;也可以使用其他静态页面生成器。现在GitHub Pages也在公测通过工作流部署静态页面&#xff0c;可以…

鸿蒙文章专题-2021年鸿蒙相关的文章废弃

#原因 至于为什么说2021年我的鸿蒙专栏的文章废弃了&#xff0c;只是说没有了参考意义&#xff0c;是因为鸿蒙4.0以前的版本语言从以Java为主过渡为以ArkTS为主。以前的Java版本的工程已经无法再使用了&#xff0c;后续的开发都必须以ArkTS开发语言为主。 其中而且整个项目结构…

三. 开发环境搭建

目录 一. Ubuntu 和 Windows 文件互传 1.1 VMware Tools 1.2 FileZilla 二. Ubuntu 下 NFS 和 SSH 服务开启 2.1 NFS 服务开启 ​编辑 2.2 SSH 服务开启 三. Ubuntu 交叉编译工具链安装 四. vscode的remote-ssh远程连接虚拟机 4.1 Windows的vscode安装 4.2 vscode远…

chatGPT的耳朵!OpenAI的开源语音识别AI:Whisper !

语音识别是通用人工智能的重要一环&#xff01;可以说是AI的耳朵&#xff01; 它可以让机器理解人类的语音&#xff0c;并将其转换为文本或其他形式的输出。 语音识别的应用场景非常广泛&#xff0c;比如智能助理、语音搜索、语音翻译、语音输入等等。 然而&#xff0c;语音…

专题1 - 双指针 - leetcode 11. 盛最多水的容器

leetcode 11. 盛最多水的容器 1. leetcode 11. 盛最多水的容器1. 题目详情1. 原题链接2. 基础框架 2. 解题思路1. 题目分析2. 算法原理3. 时间复杂度 3. 代码实现4. 知识与收获 1. leetcode 11. 盛最多水的容器 1. 题目详情 给定一个长度为 n 的整数数组 height 。有 n 条垂线…

分享一波非标设计资源合集

01 非标电表箱柜 本项目为创博智慧云产业研发中心的非标配电箱、电表箱设计原理图&#xff0c;地块一层含dwg图纸一份&#xff0c;包括配电箱壳体尺寸、原理图、接线图等20多种设计图纸。 02 住宅楼高压 低压 非标箱原理和箱体图 本图纸为高级住宅小区高低压非标箱设计原理…

Unity:Animation 三 Playable、ImportModel

目录​​​​​​​ 1. Playables API 1.1 Playable vs Animation 1.2 Advantages of using the Playables API 1.3 PlayableGraph Visualizer 2. Creating models outside of Unity 2.1 Preparing your model files for export 2.1.1 Scaling factors 2.1.2 优化模型文…

开源文生图大模型Playground v2.5发布:超越SD、DALL·E 3和 Midjourney

前言 在AI技术迅速发展的今天&#xff0c;文生图模型成为了艺术创作、设计创新等领域的重要工具。Playground v2.5的发布&#xff0c;不仅在技术上取得了突破&#xff0c;更在开源文化的推广与实践上迈出了重要一步。 Huggingface模型下载&#xff1a;https://huggingface.co/…

图论练习5

Going Home Here 解题思路 模板 二分图最优匹配&#xff0c;前提是有完美匹配&#xff08;即存在一一配对&#xff09;左右集合分别有顶标&#xff0c;当时&#xff0c;为有效边&#xff0c;即选中初始对于左集合每个点&#xff0c;选择其连边中最优的&#xff0c;然后对于每…

Sqli-labs靶场第18关详解[Sqli-labs-less-18]自动化注入-SQLmap工具注入

Sqli-labs-Less-18 通过测试发现&#xff0c;在登录界面没有注入点&#xff0c;通过已知账号密码admin&#xff0c;admin进行登录发现&#xff1a; 返回了User Agent&#xff0c;设想如果在User Agent尝试加上注入语句&#xff08;报错注入&#xff09;&#xff0c;测试是否会…

Unity中关于继承ScriptableObject的类

在游戏中我们会经常看到一些.asset的配置文件&#xff0c;而这些文件就是用一个自定义的类去继承ScriptableObject来生成的。比如当前有一些零散特效需要预加载&#xff0c;这个时候我们可以声明一个类去保存这些零散特效对象的信息&#xff0c;然后统一读取加载。 代码&#…

JavaScript极速入门(1)

初识JavaScript JavaScript是什么 JavaScript(简称JS),是一个脚本语言,解释型或者即时编译型语言.虽然它是作为开发Web页面的脚本语言而著名,但是也应用到了很多非浏览器的环境中. 看似这门语言叫JavaScript,其实在最初发明之初,这门语言的名字其实是在蹭Java的热度,实际上和…

【LeetCode】876_链表的中间结点_C

题目描述 给你单链表的头结点 head &#xff0c;请你找出并返回链表的中间结点。 如果有两个中间结点&#xff0c;则返回第二个中间结点。 https://leetcode.cn/problems/middle-of-the-linked-list/description/ 示例 提示&#xff1a; 链表的结点数范围是 [1, 100]1 <…

Subversion svn 开源的版本控制系统入门介绍 VCS

拓展阅读 Subversion 开源的版本控制系统入门介绍 VCS Git 开源的版本控制系统-01-入门使用介绍 Git 开源的版本控制系统-02-base usage 基本用法 Git 开源的版本控制系统-03-时间数据回溯 Git 开源的版本控制系统-04-branch manage 分支管理 Git 开源的版本控制系统-05-…

UE5数字孪生系列笔记(一)

智慧城市数字孪生系统 虚幻引擎连接数据库 将自己的mysql版本的libmysql.dll替换掉插件里面的libmysql.dll 然后将这个插件目录复制到虚幻项目目录下 然后添加这个插件即可 新建一个UMG&#xff0c;添加一个按钮试试&#xff0c;数据库是否连接 将UI添加到视口 打印是否连接…

力扣爆刷第87天之hot100五连刷21-25

力扣爆刷第87天之hot100五连刷21-25 文章目录 力扣爆刷第87天之hot100五连刷21-25一、240. 搜索二维矩阵 II二、160. 相交链表三、206. 反转链表四、234. 回文链表五、141. 环形链表 一、240. 搜索二维矩阵 II 题目链接&#xff1a;https://leetcode.cn/problems/search-a-2d-…

前端每日一练 :相邻元素、嵌套元素Margin 塌陷、合并问题如何额解决?

相邻元素外边距塌陷合并 表现示例 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>Document</t…

Python与FPGA——sobel边缘检测

文章目录 前言一、sobel边缘检测二、Python sobel边缘检测三、FPGA sobel边缘检测总结 前言 边缘存在于目标、背景区域之间&#xff0c;它是图像分割所依赖的较重要的依据&#xff0c;也是图像匹配的重要特征。边缘检测在图像处理和计算机视觉中&#xff0c;尤其在图像的特征提…