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

1735 0
王子 2022-11-9 09:40:37 | 显示全部楼层 |阅读模式
目录

    一、滑动验证码生成思路二、主要方法三、生成代码四、测试结果


一、滑动验证码生成思路

1、随机选择一张图片
2、生成滑块起点位置(x, y)
3、生成滑块轮廓
4、抠出滑块
5、将滑块部位去除颜色



二、主要方法

这里使用的方法是:先抠出中间的正方形,再将凹凸槽的RGB渲染上去
1、扣主体
将自定义滑块大小扩大三分之二,用来做凸槽
2、抠凸槽


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

三、生成代码

滑块验证码实体类
  1. import lombok.AllArgsConstructor;
  2. import lombok.Data;
  3. import lombok.NoArgsConstructor;
  4. /**
  5. * @author: Yang
  6. * @create: 2022-10-25
  7. * @Description: 滑动验证码实体
  8. */
  9. @Data
  10. @AllArgsConstructor
  11. @NoArgsConstructor
  12. public class ImageSlideVerify {
  13.     private String bgImg;// 底部图片
  14.     private String blockImg;// 滑块图片
  15.     private Integer x;// 开始x
  16.     private Integer y;// 开始y
  17.     private Integer bound;// 误差值
  18. }
复制代码
生成滑块验证码
  1. import com.yang.domain.vo.ImageSlideVerify;
  2. import org.apache.tomcat.util.codec.binary.Base64;
  3. import java.awt.Color;
  4. import java.awt.Graphics2D;
  5. import java.awt.Transparency;
  6. import java.awt.image.BufferedImage;
  7. import java.io.ByteArrayOutputStream;
  8. import java.io.File;
  9. import java.io.FileInputStream;
  10. import java.io.IOException;
  11. import java.util.Random;
  12. import java.util.UUID;
  13. import javax.imageio.ImageIO;
  14. /**
  15. * 滑动验证码
  16. * @author Yang
  17. *
  18. */
  19. public class ImageSlideVerifyUtil {
  20.         private static Integer x, y;// x , y轴起点位置
  21.         private static Integer blockSize; // 块大小
  22.         public static void main(String[] args) throws IOException {
  23.                 File file = new File("4.jpeg");
  24.                 cutting(file, 80);
  25.                 cutting(file);
  26.         }
  27.         // 切割
  28.         public static ImageSlideVerify cutting(File file, int size) {
  29.                 FileInputStream fis;
  30.                 blockSize = size;
  31.                 try {
  32.                         fis = new FileInputStream(file);
  33.                         BufferedImage image = ImageIO.read(fis);// 将文件流转图像流
  34.                         // 生成圆位置
  35.                         Integer cp[] = circle();// 下标对应:上右下左
  36.                         // 生成滑块
  37.                         BufferedImage img = generateMin(image, image.getWidth(), image.getHeight(), size, cp);
  38.                         // 图片转base64
  39.                         String bgImg = imageToBase64(image);
  40.                         String blockImg = imageToBase64(img);
  41.                         // TODO 保存图片:用于测试,测试完毕删除
  42.                         // ImageIO.write(img, "png", new File("4-1.png"));
  43.                         // ImageIO.write(image, "png", new File("4-2.png"));
  44.                         ImageSlideVerify imageSlideVerify = new ImageSlideVerify(bgImg, blockImg, x, y, 3);
  45.                         return imageSlideVerify;
  46.                 } catch (IOException e) {
  47.                         e.printStackTrace();
  48.                 }
  49.                 return null;
  50.         }
  51.         // 切割
  52.         public static ImageSlideVerify cutting(File file) {
  53.                 return cutting(file, 60);
  54.         }
  55.         // 圆的位置
  56.         private static Integer[] circle() {
  57.                 Integer c[] = new Integer[4];// 四个位置有圆,0代表无,1代表有,下标对应上、右、下、左
  58.                 boolean flag = false;// 记录是否有圆
  59.                 while(!flag) {// 如果没有圆,则继续循环,至少要有一个圆(凸槽)
  60.                         for(int i = 0; i < 4; i++) {
  61.                                 c[i] = new Random().nextInt(2);
  62.                                 if(c[i] == 1) {
  63.                                         flag = true;
  64.                                 }
  65.                         }
  66.                 }
  67.                 return c;
  68.         }
  69.         /**
  70.          * 生成小滑块位置
  71.          * @param img
  72.          * @param width 图片宽度
  73.          * @param height 图片高度
  74.          * @param size 滑块大小, 正方形,宽高相等
  75.          * @return
  76.          * @throws IOException
  77.          */
  78.         private static BufferedImage generateMin(BufferedImage img, int width, int height, int size, Integer[] cp) throws IOException {
  79.                 /**
  80.                  * 滑块大小:定义大小 + 三分之一
  81.                  */
  82.                 int size1 = size + (size / 3 * 2);
  83.                 /**
  84.                  * 最大起点位置
  85.                  *         x:宽度 - 滑块大小
  86.                  *  y:高度 - 滑块大小
  87.                  */
  88.                 int maxX = width - ( size1 );
  89.                 int maxY = height - ( size1 );
  90.                 // 生成滑块开始位置
  91.                 x = new Random().nextInt(maxX);
  92.                 y = new Random().nextInt(maxY);
  93.                 // 创建滑块图像
  94.                 BufferedImage img1 = new BufferedImage(size1, size1, BufferedImage.TYPE_INT_RGB);
  95.                 Graphics2D gr = img1.createGraphics();
  96.                 // 图像背景透明
  97.                 img1 = gr.getDeviceConfiguration().createCompatibleImage(size1, size1, Transparency.TRANSLUCENT);
  98.                 // 拷贝rgb
  99.                 for(int i = 0; i < size1; i++) {
  100.                         for(int j = 0; j < size1; j++) {
  101.                                 if(i < size / 3 || i > size + size / 3 || j < size / 3 || j > size + size / 3) {
  102.                                         continue;
  103.                                 }
  104.                                 // 渲染RGB
  105.                                 img1.setRGB(i, j, img.getRGB(i + x, j + y));
  106.                                 // 将原图像素点覆盖白色
  107.                                 Color color = new Color(255,255,255);
  108.                                 img.setRGB(i + x, j + y, color.getRGB());
  109.                         }
  110.                 }
  111.                 // 设置圆(凸槽)
  112.                 setCircle(img, img1, x, y, cp);
  113.                 return img1;
  114.         }
  115.         /**
  116.          * 设置圆
  117.          * @param oldImg
  118.          * @param img
  119.          * @param x
  120.          * @param y
  121.          * @param cp
  122.          * @throws IOException
  123.          */
  124.         private static void setCircle(BufferedImage oldImg, BufferedImage img, int x, int y, Integer[] cp) throws IOException {
  125.                 // 以白色覆盖原图像素点
  126.                 Color color = new Color(255,255,255);
  127.                 int d = blockSize / 3 + 2; // 直径
  128.                 int r = d / 2;// 半径
  129.                 /**
  130.                  * TODO 以下待改进
  131.                  */
  132.                 if(cp[0] == 1) {// 上
  133.                         // 中心位置
  134.                         int w = img.getWidth() / 2;
  135.                         for(int i = w - r, r1 = 0; i < w + r; i++, r1++) {
  136.                                 for(int j = 0, r2 = 0; j < d; j++, r2++) {
  137.                                         /**
  138.                                          * 判断点是否在圆内:点p(x, y), 圆心r(x, y)
  139.                                          * 有:(px - rx)^2 + (py - ry)^2 <= rx*ry
  140.                                          */
  141.                                         if((r1 - r) * (r1 - r) + (r2 - r) * (r2 - 11) <= r * r) {
  142.                                                 if(oldImg.getRGB(x + i, y + j) == color.getRGB()) {
  143.                                                         continue;
  144.                                                 }
  145.                                                 img.setRGB(i, j, oldImg.getRGB(x + i, y + j));
  146.                                                 // 对应位置透明
  147.                                                 oldImg.setRGB(x + i, y + j, color.getRGB());
  148.                                         }
  149.                                 }
  150.                         }
  151.                 }
  152.                 if(cp[1] == 1) {// 右
  153.                         // 中心位置
  154.                         int h = img.getHeight() / 2;
  155.                         for(int i = img.getWidth() - d, r1 = 0; i < img.getWidth(); i++, r1++) {
  156.                                 for(int j = h - r, r2 = 0; j < h + r; j++, r2++) {
  157.                                         if((r1 - r) * (r1 - r) + (r2 - r) * (r2 - r) <= r * r) {
  158.                                                 if(oldImg.getRGB(x + i, y + j) == color.getRGB()) continue;
  159.                                                 img.setRGB(i, j, oldImg.getRGB(x + i, y + j));
  160.                                                 // 对应位置透明
  161.                                                 oldImg.setRGB(x + i, y + j, color.getRGB());
  162.                                         }
  163.                                 }
  164.                         }
  165.                 }
  166.                 if(cp[2] == 1) {// 下
  167.                         // 中心位置
  168.                         int w = img.getWidth() / 2;
  169.                         for(int i = w - r, r1 = 0; i < w + r; i++, r1++) {
  170.                                 for(int j = img.getHeight() - d, r2 = 0; j < img.getHeight(); j++, r2++) {
  171.                                         if((r1 - r) * (r1 - r) + (r2 - r) * (r2 - r) <= r * r) {
  172.                                                 if(oldImg.getRGB(x + i, y + j) == color.getRGB()) continue;
  173.                                                 img.setRGB(i, j, oldImg.getRGB(x + i, y + j));
  174.                                                 // 对应位置透明
  175.                                                 oldImg.setRGB(x + i, y + j, color.getRGB());
  176.                                         }
  177.                                 }
  178.                         }
  179.                 }
  180.                 if(cp[3] == 1) {// 左
  181.                         // 中心位置
  182.                         int h = img.getHeight() / 2;
  183.                         for(int i = 0, r1 = 0; i < d; i++, r1++) {
  184.                                 for(int j = h - r, r2 = 0; j < h + r; j++, r2++) {
  185.                                         if((r1 - r) * (r1 - r) + (r2 - r) * (r2 - r) <= r * r) {
  186.                                                 if(oldImg.getRGB(x + i, y + j) == color.getRGB()) continue;
  187.                                                 img.setRGB(i, j, oldImg.getRGB(x + i, y + j));
  188.                                                 // 对应位置透明
  189.                                                 oldImg.setRGB(x + i, y + j, color.getRGB());
  190.                                         }
  191.                                 }
  192.                         }
  193.                 }
  194.         }
  195.         /**
  196.          * 图像转base64
  197.          * @param img
  198.          * @return
  199.          */
  200.         private static String imageToBase64(BufferedImage img){
  201.                 ByteArrayOutputStream stream = new ByteArrayOutputStream();
  202.                 try {
  203.                         // 设置图片的格式
  204.                         ImageIO.write(img, "png", stream);
  205.                         byte[] bytes = Base64.encodeBase64(stream.toByteArray());
  206.                         String base64 = new String(bytes);
  207.                         return  "data:image/jpeg;base64,"+base64;
  208.                 } catch (IOException e) {
  209.                         e.printStackTrace();
  210.                 }
  211.                 return null;
  212.         }
  213. }
复制代码
四、测试结果





这里看滑块是白色背景,实际上是透明的
生成完成
web前端代码
到此这篇关于Java实现滑动验证码生成(后端工具类)的文章就介绍到这了,更多相关Java滑动验证码内容请搜索中国红客联盟以前的文章或继续浏览下面的相关文章希望大家以后多多支持中国红客联盟!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

中国红客联盟公众号

联系站长QQ:5520533

admin@chnhonker.com
Copyright © 2001-2025 Discuz Team. Powered by Discuz! X3.5 ( 粤ICP备13060014号 )|天天打卡 本站已运行