Java实现滑动验证码生成(后端工具类)

 更新时间:2022年10月27日 14:49:39   作者:weixin_52707625  
这篇文章主要为大家详细介绍了Java实现滑动验证码生成功能中的后端工具类部分,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下

一、滑动验证码生成思路

1、随机选择一张图片

2、生成滑块起点位置(x, y)

3、生成滑块轮廓

4、抠出滑块

5、将滑块部位去除颜色

二、主要方法

这里使用的方法是:先抠出中间的正方形,再将凹凸槽的RGB渲染上去

1、扣主体

将自定义滑块大小扩大三分之二,用来做凸槽

2、抠凸槽

因为凸槽是个圆,所以可通过圆的标准方程

三、生成代码

滑块验证码实体类

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

/**
 * @author: Yang
 * @create: 2022-10-25
 * @Description: 滑动验证码实体
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
public class ImageSlideVerify {

    private String bgImg;// 底部图片
    private String blockImg;// 滑块图片
    private Integer x;// 开始x
    private Integer y;// 开始y
    private Integer bound;// 误差值
}

生成滑块验证码

import com.yang.domain.vo.ImageSlideVerify;
import org.apache.tomcat.util.codec.binary.Base64;

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Transparency;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Random;
import java.util.UUID;

import javax.imageio.ImageIO;

/**
 * 滑动验证码
 * @author Yang
 *
 */
public class ImageSlideVerifyUtil {
	
	private static Integer x, y;// x , y轴起点位置
	private static Integer blockSize; // 块大小

	public static void main(String[] args) throws IOException {
		File file = new File("4.jpeg");
		cutting(file, 80);
		cutting(file);
	}
	
	
	// 切割
	public static ImageSlideVerify cutting(File file, int size) {
		FileInputStream fis;
		blockSize = size;
		
		try {
			fis = new FileInputStream(file);
			BufferedImage image = ImageIO.read(fis);// 将文件流转图像流
			
			// 生成圆位置
			Integer cp[] = circle();// 下标对应:上右下左
			
			// 生成滑块
			BufferedImage img = generateMin(image, image.getWidth(), image.getHeight(), size, cp);
			// 图片转base64
			String bgImg = imageToBase64(image);
			String blockImg = imageToBase64(img);
			// TODO 保存图片:用于测试,测试完毕删除
			// ImageIO.write(img, "png", new File("4-1.png"));
			// ImageIO.write(image, "png", new File("4-2.png"));
			
			ImageSlideVerify imageSlideVerify = new ImageSlideVerify(bgImg, blockImg, x, y, 3);

			return imageSlideVerify;
		} catch (IOException e) {
			e.printStackTrace();
		}
		return null;
	}
	// 切割
	public static ImageSlideVerify cutting(File file) {
		return cutting(file, 60);
	}
	
	// 圆的位置
	private static Integer[] circle() {
		
		Integer c[] = new Integer[4];// 四个位置有圆,0代表无,1代表有,下标对应上、右、下、左
		boolean flag = false;// 记录是否有圆
		while(!flag) {// 如果没有圆,则继续循环,至少要有一个圆(凸槽)
			for(int i = 0; i < 4; i++) {
				c[i] = new Random().nextInt(2);
				if(c[i] == 1) {
					flag = true;
				}
			}
		}
		return c;
	}
	
	/**
	 * 生成小滑块位置
	 * @param img
	 * @param width 图片宽度
	 * @param height 图片高度
	 * @param size 滑块大小, 正方形,宽高相等
	 * @return
	 * @throws IOException 
	 */
	private static BufferedImage generateMin(BufferedImage img, int width, int height, int size, Integer[] cp) throws IOException {

		/**
		 * 滑块大小:定义大小 + 三分之一
		 */
		int size1 = size + (size / 3 * 2);
		/**
		 * 最大起点位置
		 * 	x:宽度 - 滑块大小
		 *  y:高度 - 滑块大小
		 */
		int maxX = width - ( size1 );
		int maxY = height - ( size1 );
		
		// 生成滑块开始位置
		x = new Random().nextInt(maxX);
		y = new Random().nextInt(maxY);
		// 创建滑块图像
		BufferedImage img1 = new BufferedImage(size1, size1, BufferedImage.TYPE_INT_RGB);
		Graphics2D gr = img1.createGraphics();
		// 图像背景透明
		img1 = gr.getDeviceConfiguration().createCompatibleImage(size1, size1, Transparency.TRANSLUCENT);
		
		// 拷贝rgb
		for(int i = 0; i < size1; i++) {
			for(int j = 0; j < size1; j++) {
				if(i < size / 3 || i > size + size / 3 || j < size / 3 || j > size + size / 3) {
					continue;
				}
				// 渲染RGB
				img1.setRGB(i, j, img.getRGB(i + x, j + y));
				// 将原图像素点覆盖白色
				Color color = new Color(255,255,255);
				img.setRGB(i + x, j + y, color.getRGB());
			}
		}
		// 设置圆(凸槽)
		setCircle(img, img1, x, y, cp);
		return img1;
	}
	/**
	 * 设置圆
	 * @param oldImg
	 * @param img
	 * @param x
	 * @param y
	 * @param cp
	 * @throws IOException 
	 */
	private static void setCircle(BufferedImage oldImg, BufferedImage img, int x, int y, Integer[] cp) throws IOException {
		// 以白色覆盖原图像素点
		Color color = new Color(255,255,255);

		int d = blockSize / 3 + 2; // 直径
		int r = d / 2;// 半径
		/**
		 * TODO 以下待改进
		 */
		if(cp[0] == 1) {// 上
			// 中心位置
			int w = img.getWidth() / 2;
			
			for(int i = w - r, r1 = 0; i < w + r; i++, r1++) {
				for(int j = 0, r2 = 0; j < d; j++, r2++) {
					/**
					 * 判断点是否在圆内:点p(x, y), 圆心r(x, y)
					 * 有:(px - rx)^2 + (py - ry)^2 <= rx*ry
					 */
					if((r1 - r) * (r1 - r) + (r2 - r) * (r2 - 11) <= r * r) {
						if(oldImg.getRGB(x + i, y + j) == color.getRGB()) {
							continue;
						}
						img.setRGB(i, j, oldImg.getRGB(x + i, y + j));
						// 对应位置透明
						oldImg.setRGB(x + i, y + j, color.getRGB());
					}
				}
			}
		}
		if(cp[1] == 1) {// 右
			// 中心位置
			int h = img.getHeight() / 2;
			for(int i = img.getWidth() - d, r1 = 0; i < img.getWidth(); i++, r1++) {
				for(int j = h - r, r2 = 0; j < h + r; j++, r2++) {
					if((r1 - r) * (r1 - r) + (r2 - r) * (r2 - r) <= r * r) {
						if(oldImg.getRGB(x + i, y + j) == color.getRGB()) continue;
						img.setRGB(i, j, oldImg.getRGB(x + i, y + j));
						// 对应位置透明
						oldImg.setRGB(x + i, y + j, color.getRGB());
					}
				}
			}
		}
		if(cp[2] == 1) {// 下
			// 中心位置
			int w = img.getWidth() / 2;
			
			for(int i = w - r, r1 = 0; i < w + r; i++, r1++) {
				for(int j = img.getHeight() - d, r2 = 0; j < img.getHeight(); j++, r2++) {
					if((r1 - r) * (r1 - r) + (r2 - r) * (r2 - r) <= r * r) {
						if(oldImg.getRGB(x + i, y + j) == color.getRGB()) continue;
						img.setRGB(i, j, oldImg.getRGB(x + i, y + j));
						// 对应位置透明
						oldImg.setRGB(x + i, y + j, color.getRGB());
					}
				}
			}
		}
		if(cp[3] == 1) {// 左
			// 中心位置
			int h = img.getHeight() / 2;
			for(int i = 0, r1 = 0; i < d; i++, r1++) {
				for(int j = h - r, r2 = 0; j < h + r; j++, r2++) {
					if((r1 - r) * (r1 - r) + (r2 - r) * (r2 - r) <= r * r) {
						if(oldImg.getRGB(x + i, y + j) == color.getRGB()) continue;
						img.setRGB(i, j, oldImg.getRGB(x + i, y + j));
						// 对应位置透明
						oldImg.setRGB(x + i, y + j, color.getRGB());
					}
				}
			}
		}
	}

	/**
	 * 图像转base64
	 * @param img
	 * @return
	 */
	private static String imageToBase64(BufferedImage img){
		ByteArrayOutputStream stream = new ByteArrayOutputStream();
		try {
			// 设置图片的格式
			ImageIO.write(img, "png", stream);
			byte[] bytes = Base64.encodeBase64(stream.toByteArray());
			String base64 = new String(bytes);
			return  "data:image/jpeg;base64,"+base64;
		} catch (IOException e) {
			e.printStackTrace();
		}
		return null;
	}
}

四、测试结果

这里看滑块是白色背景,实际上是透明的

生成完成

web前端代码

到此这篇关于Java实现滑动验证码生成(后端工具类)的文章就介绍到这了,更多相关Java滑动验证码内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 初探Spring Cloud Gateway实战

    初探Spring Cloud Gateway实战

    这篇文章主要介绍了创建网关项目(Spring Cloud Gateway)过程详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2021-08-08
  • 详解Java中HashSet和TreeSet的区别

    详解Java中HashSet和TreeSet的区别

    这篇文章主要介绍了详解Java中HashSet和TreeSet的区别的相关资料,需要的朋友可以参考下
    2017-06-06
  • java利用Future实现多线程执行与结果聚合实例代码

    java利用Future实现多线程执行与结果聚合实例代码

    这篇文章主要给大家介绍了关于java利用Future实现多线程执行与结果聚合的相关资料,Future模式的核心,去除了主函数的等待时间,并使得原本需要等待的时间段可以用于处理其他业务逻辑,需要的朋友可以参考下
    2021-12-12
  • Java实现Linux下双守护进程

    Java实现Linux下双守护进程

    这篇文章主要介绍了Java实现Linux下双守护进程的思路、原理以及具体实现方式,非常的详细,希望对大家有所帮助
    2014-10-10
  • java Comparator.comparing排序使用示例

    java Comparator.comparing排序使用示例

    本文主要介绍了java Comparator.comparing排序使用示例,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-10-10
  • 解决springboot读取application.properties中文乱码问题

    解决springboot读取application.properties中文乱码问题

    初用properties,读取java properties文件的时候如果value是中文,会出现乱码的问题,所以本文小编将给大家介绍如何解决springboot读取application.properties中文乱码问题,需要的朋友可以参考下
    2023-11-11
  • SpringMVC HttpMessageConverter消息转换器

    SpringMVC HttpMessageConverter消息转换器

    ​​HttpMessageConverter​​​,报文信息转换器,将请求报文转换为Java对象,或将Java对象转换为响应报文。​​​HttpMessageConverter​​​提供了两个注解和两个类型:​​@RequestBody,@ResponseBody​​​,​​RequestEntity,ResponseEntity​​
    2023-04-04
  • Java设计模式之责任链模式简介

    Java设计模式之责任链模式简介

    这篇文章主要介绍了Java设计模式之责任链模式,需要的朋友可以参考下
    2014-07-07
  • 解决idea使用过程中让你觉得不爽的一些问题(小结)

    解决idea使用过程中让你觉得不爽的一些问题(小结)

    这篇文章主要介绍了解决idea使用过程中让你觉得不爽的一些问题,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-08-08
  • Spring Boot使用模板freemarker的示例代码

    Spring Boot使用模板freemarker的示例代码

    本篇文章主要介绍了Spring Boot使用模板freemarker的示例代码,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-10-10

最新评论