import io.swagger.annotations.ApiModelProperty;
import lombok.Data;/*** @Author: zengms* @Description:* @Date: 2021-11-01*/
@Data
public class ImageDto {@ApiModelProperty(value = "图片的长")private Integer width;@ApiModelProperty(value = "图片的高")private Integer height;@ApiModelProperty(value = "图片信息")private String imageBase64;
}
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;/*** @Author: zengms* @Description:* @Date: 2021-11-01*/
@Data
public class ImageVerifyDto {@ApiModelProperty(value = "大图信息")private ImageDto bigImage;@ApiModelProperty(value = "小图信息")private ImageDto smallImage;@ApiModelProperty(value = "小图y坐标")private Integer yHeight;@ApiModelProperty(value = "小图x坐标")private Integer xWidth;
}
package org.code.modules.system.util;import lombok.extern.slf4j.Slf4j;
import org.code.modules.system.model.ImageDto;
import org.code.modules.system.model.ImageVerifyDto;
import org.springframework.util.Base64Utils;
import sun.misc.BASE64Encoder;import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.Random;/*** @Author: zengms* @Description:滑块拼图验证码* @Date: 2021-10-28*/
@Slf4j
public class SlipImageUtil {private static int targetWidth = 180;//小图长(根据原图的大小设置滑动图片的长度)private static int targetHeight = 160;//小图宽(根据原图的大小设置滑动图片的高度)private static int circleR = 25;//半径(根据原图的大小设置滑半径的大小)private static int r1 = 20;//距离点(根据原图的大小设置距离点的大小)/*** base64 图片前缀*/private static final String BASE64_PNG = "data:image/png;base64,";private static final String BASE64_JPG = "data:image/jpg;base64,";/*** 图片格式*/private static final String IMG_FORMAT_PNG = "png";private static final String IMG_FORMAT_JPG = "jpg";/*** @Description: 生成小图轮廓*/private static int[][] getBlockData() {int[][] data = new int[targetWidth][targetHeight];double x2 = targetWidth -circleR; //47//随机生成圆的位置double h1 = circleR + Math.random() * (targetWidth-3*circleR-r1);double po = Math.pow(circleR,2); //64double xbegin = targetWidth - circleR - r1;double ybegin = targetHeight- circleR - r1;//圆的标准方程 (x-a)²+(y-b)²=r²,标识圆心(a,b),半径为r的圆//计算需要的小图轮廓,用二维数组来表示,二维数组有两张值,0和1,其中0表示没有颜色,1有颜色for (int i = 0; i < targetWidth; i++) {for (int j = 0; j < targetHeight; j++) {double d2 = Math.pow(j - 2,2) + Math.pow(i - h1,2);double d3 = Math.pow(i - x2,2) + Math.pow(j - h1,2);if ((j <= ybegin && d2 < po)||(i >= xbegin && d3 > po)) {data[i][j] = 0;}  else {data[i][j] = 1;}}}return data;}/**** @Description: 有这个轮廓后就可以依据这个二维数组的值来判定抠图并在原图上抠图位置处加阴影,* @param oriImage  原图* @param targetImage  抠图拼图* @param templateImage 颜色* @param x* @param y* @throws*/private static void cutByTemplate(BufferedImage oriImage, BufferedImage targetImage, int[][] templateImage, int x, int y){int[][] martrix = new int[3][3];int[] values = new int[9];//创建shape区域for (int i = 0; i < targetWidth; i++) {for (int j = 0; j < targetHeight; j++) {int rgb = templateImage[i][j];// 原图中对应位置变色处理int rgb_ori = oriImage.getRGB(x + i, y + j);if (rgb == 1) {targetImage.setRGB(i, j, rgb_ori);//抠图区域高斯模糊readPixel(oriImage, x + i, y + j, values);fillMatrix(martrix, values);oriImage.setRGB(x + i, y + j, avgMatrix(martrix));}else{//这里把背景设为透明targetImage.setRGB(i, j, rgb_ori & 0x00ffffff);}}}}private static void readPixel(BufferedImage img, int x, int y, int[] pixels) {int xStart = x - 1;int yStart = y - 1;int current = 0;for (int i = xStart; i < 3 + xStart; i++)for (int j = yStart; j < 3 + yStart; j++) {int tx = i;if (tx < 0) {tx = -tx;} else if (tx >= img.getWidth()) {tx = x;}int ty = j;if (ty < 0) {ty = -ty;} else if (ty >= img.getHeight()) {ty = y;}pixels[current++] = img.getRGB(tx, ty);}}private static void fillMatrix(int[][] matrix, int[] values) {int filled = 0;for (int i = 0; i < matrix.length; i++) {int[] x = matrix[i];for (int j = 0; j < x.length; j++) {x[j] = values[filled++];}}}private static int avgMatrix(int[][] matrix) {int r = 0;int g = 0;int b = 0;for (int i = 0; i < matrix.length; i++) {int[] x = matrix[i];for (int j = 0; j < x.length; j++) {if (j == 1) {continue;}Color c = new Color(x[j]);r += c.getRed();g += c.getGreen();b += c.getBlue();}}return new Color(r / 8, g / 8, b / 8).getRGB();}/*** 读取本地图片,生成拼图验证码* 返回生成的抠图和带抠图阴影的大图 base64码及抠图坐标*/public static ImageVerifyDto createImage(File file){ImageVerifyDto returnDto = new ImageVerifyDto();ImageDto bigImage = new ImageDto();ImageDto smallImage = new ImageDto();try {BufferedImage bigBufferedImage = ImageIO.read(file);Random random = new Random();//X轴距离右端targetWidth  Y轴距离底部targetHeight以上int widthRandom = random.nextInt(bigBufferedImage.getWidth()-  2*targetWidth) + targetWidth;int heightRandom = random.nextInt(bigBufferedImage.getHeight()- targetHeight);log.info("原图大小{} x {},随机生成的坐标 X,Y 为({},{})",bigBufferedImage.getWidth(),bigBufferedImage.getHeight(),widthRandom,heightRandom);BufferedImage smallBufferedImage= new BufferedImage(targetWidth, targetHeight, BufferedImage.TYPE_4BYTE_ABGR);cutByTemplate(bigBufferedImage,smallBufferedImage,getBlockData(),widthRandom,heightRandom);bigImage.setWidth(bigBufferedImage.getWidth());//大图的宽bigImage.setHeight(bigBufferedImage.getHeight());//大图的高bigImage.setImageBase64(BASE64_JPG+ getImageToBase64(bigBufferedImage,IMG_FORMAT_JPG));//大图returnDto.setBigImage(bigImage);smallImage.setWidth(smallBufferedImage.getWidth());//小图的宽smallImage.setHeight(smallBufferedImage.getHeight());//小图的高smallImage.setImageBase64(BASE64_PNG+ getImageToBase64(smallBufferedImage,IMG_FORMAT_PNG));//小图,小图要转PNG背景色才不会变黑returnDto.setSmallImage(smallImage);returnDto.setXWidth(widthRandom);//小图x坐标returnDto.setYHeight(heightRandom);//小图y坐标} catch (Exception e) {log.error("创建图形验证码异常",e);} finally{return returnDto;}}/*** 读取网络图片,生成拼图验证码* 返回生成的抠图和带抠图阴影的大图 base64码及抠图坐标*/public static ImageVerifyDto createImage(String imgUrl){ImageVerifyDto returnDto = new ImageVerifyDto();ImageDto bigImage = new ImageDto();ImageDto smallImage = new ImageDto();try {//通过URL 读取图片URL url = new URL(imgUrl);BufferedImage bigBufferedImage = ImageIO.read(url.openStream());Random rand = new Random();int widthRandom = rand.nextInt(bigBufferedImage.getWidth()-  targetWidth - 100 + 1 ) + 100;int heightRandom = rand.nextInt(bigBufferedImage.getHeight()- targetHeight + 1 );log.info("原图大小{} x {},随机生成的坐标 X,Y 为({},{})",bigBufferedImage.getWidth(),bigBufferedImage.getHeight(),widthRandom,heightRandom);BufferedImage smallBufferedImage= new BufferedImage(targetWidth, targetHeight, BufferedImage.TYPE_4BYTE_ABGR);cutByTemplate(bigBufferedImage,smallBufferedImage,getBlockData(),widthRandom,heightRandom);bigImage.setWidth(bigBufferedImage.getWidth());//大图的宽bigImage.setHeight(bigBufferedImage.getHeight());//大图的高bigImage.setImageBase64(BASE64_JPG+ getImageToBase64(bigBufferedImage,IMG_FORMAT_JPG));//大图returnDto.setBigImage(bigImage);smallImage.setWidth(smallBufferedImage.getWidth());//小图的宽smallImage.setHeight(smallBufferedImage.getHeight());//小图的高smallImage.setImageBase64(BASE64_PNG+ getImageToBase64(smallBufferedImage,IMG_FORMAT_PNG));//小图,小图要转PNG背景色才不会变黑returnDto.setSmallImage(smallImage);returnDto.setXWidth(widthRandom);//小图x坐标returnDto.setYHeight(heightRandom);//小图y坐标} catch (Exception e) {log.error("创建图形验证码异常",e);} finally{return returnDto;}}/*** @Description: 图片转BASE64* @param image* @return* @throws IOException String*/public static String getImageBASE64(BufferedImage image) throws IOException {byte[] imagedata = null;ByteArrayOutputStream bao=new ByteArrayOutputStream();ImageIO.write(image,IMG_FORMAT_PNG,bao);imagedata=bao.toByteArray();BASE64Encoder encoder = new BASE64Encoder();String BASE64IMAGE=encoder.encodeBuffer(imagedata).trim();BASE64IMAGE = BASE64IMAGE.replaceAll("\r|\n", "");  //删除 \r\nreturn BASE64IMAGE;}/*** @Description: 图片转BASE64* @param image* @return* @throws IOException String*/public static String getImageToBase64(BufferedImage image, String imageType) throws IOException {ByteArrayOutputStream byteBigStream = new ByteArrayOutputStream();//写入流中ImageIO.write(image, imageType, byteBigStream);byte[] bytes_big = byteBigStream.toByteArray();return Base64Utils.encodeToString(bytes_big);}public static void main(String[] args) {ImageVerifyDto dto = SlipImageUtil.createImage("http://xxxx/1.jpg");//图片地址,原图大小800*500System.out.println("bigImage:\n"+dto.getBigImage().getImageBase64());System.out.println("smallImage:\n"+dto.getSmallImage().getImageBase64());}}
    @ApiOperation(value = "获取图形验证码")@RequestMapping(value = "/getImageVerify/{checkKey}", method = RequestMethod.GET)@ResponseBodypublic Result<ImageVerifyDto> getImageVerifyCode(@PathVariable String checkKey) {String imageUrl = "http://xxxx/1.jpg";//读取网络图片ImageVerifyDto imageVerifyDto = SlipImageUtil.createImage(imageUrl);//验证码2分钟内有效redisUtil.set("imageCode:" + checkKey, imageVerifyDto.getXWidth(), 120);imageVerifyDto.setXWidth(null);return Result.ok(imageVerifyDto);}
    //moveLength:拖动的距离@ApiOperation(value = "验证图形验证码")@RequestMapping(value = "/checkImageVerifyCode", method = RequestMethod.GET)@ResponseBodypublic Result<?> checkImageVerifyCode(@RequestParam(value = "moveLength", required = true) Double moveLength,@RequestParam(value = "checkKey", required = true) String checkKey) {if (null == moveLength) {return Result.error("验证失败");}Object obj = redisUtil.get("imageCode:" + checkKey);if(null == obj){return Result.error("验证过期,请重试");}Integer xWidth = (Integer) obj;if (Math.abs(xWidth - moveLength) > 10) {return Result.error("验证不通过");} else {redisUtil.del("imageCode:" + checkKey);return Result.ok("验证通过");}}

JAVA 滑块拼图验证码相关推荐

  1. 拼图java监听器,Android 简单的实现滑块拼图验证码功能

    实现滑块拼图验证码功能之前已经写过一篇了,上一篇使用的是自定义控件的方式实现这个功能,主要还是想让童鞋们知其然更知其所以然,还没看的童鞋可以先看看Android实现滑块拼图验证码功能这篇. 在项目的开 ...

  2. JAVA 完整实现滑块拼图验证码

    后端随机生成抠图和带有抠图阴影的背景图片,后台保存随机抠图位置坐标 前端实现滑动交互,将抠图拼在抠图阴影之上,获取到用户滑动距离值,比如以下示例 前端将用户滑动距离值传入后端,后端校验误差是否在容许范 ...

  3. JAVA 模板抠图生成滑块拼图验证码原理及实现

    实现效果图: 滑块验证码原理 很多网站使用滑块验证码提高网站安全性,为了做到真正的验证,必须要走后台服务器. 下面是java实现滑块验证的核心步骤: 1.从服务器随机取一张底透明有形状的模板图,再随机 ...

  4. c语言拼图验证码编写,Android 简单的实现滑块拼图验证码功能

    实现滑块拼图验证码功能之前已经写过一篇了,上一篇使用的是自定义控件的方式实现这个功能,主要还是想让童鞋们知其然更知其所以然,还没看的童鞋可以先看看Android实现滑块拼图验证码功能这篇. 在项目的开 ...

  5. android滑动图形验证码,Android使用更简单的方式实现滑块拼图验证码功能

    实现滑块拼图验证码功能之前已经写过一篇了,上一篇使用的是自定义控件的方式实现这个功能,主要还是想让童鞋们知其然更知其所以然,还没看的童鞋可以先看看Android实现滑块拼图验证码功能这篇. 在项目的开 ...

  6. Python实战 | 滑块拼图验证码高级版详解

    目录 1.如何实现滑块拼图验证码高级版? 2.HTML代码: 3.Python代码: 4.执行后报错,解决方案: 5.完整代码,修改后如下: 1.如何实现滑块拼图验证码高级版? 2.HTML代码: & ...

  7. Android滑块拼图验证码控件

    转自  王小冉的文章:https://blog.csdn.net/w690333243/article/details/90311187 https://github.com/luozhanming/ ...

  8. c语言拼图验证码编写,java实现拼图验证码

    最近项目需要将原有的图形验证码更换为拼图验证,开始去网上搜了一些相关的DEMO,发现做这个的DEMO很少.不得已,只能自己慢慢摸索啦. 经过几天的坑,算是基本完成了需求.现分享下实现的过程 DEMO效 ...

  9. Java Vue uni-app 三端实现,滑动拼图验证码

    一步一步实现 图片滑动验证码 项目中要使用 图片滑动验证码,顾了解之 需要以下几步来完成: 1.后端随机计算抠图的距离,生成背景与拼图块的图片,缓存 拼图块需 滑动的距离像素. 2.前端加载背景图 和 ...

  10. Android 滑动拼图验证码控件

    Android 滑动拼图验证码控件 简介: 很多软件为了安全防止恶意攻击,会在登录/注册时进行人机验证,常见的人机验证方式有:谷歌点击复选框进行验证,输入验证码验证,短信验证码,语音验证,文字按顺序选 ...

最新文章

  1. C++ 文本查询2.0(逻辑查询)
  2. 来学学数据分析吧(二)第一章 预测和关联数量特征
  3. response.sendRedirect()重新定向的乱码问题
  4. 自学python转行-转行Python,应该如何短期自学,达到就业水平
  5. [翻译] - Inside SQL Server 2000's Memory Management Facilities
  6. spring二:装配bean(自动装配)
  7. channelread0会被调用两次_值得一看:C#同步方法中如何调用异步方法?
  8. 八十九、Python的GUI系列 | 使用PyQt5 快速构建一个GUI 应用
  9. CrashFinder,找到崩溃代码行
  10. 后端学习 - 并发编程
  11. 汇编语言 test 和 cmp 区别
  12. OSSemPend()--等待一个信号量
  13. 快速配置vs2012+opencv
  14. [转]架构师的职责及工作描述
  15. ElementUI:定制日历Calendar
  16. 微信网页授权失败原因总结
  17. WebWall-02.Burt Force(暴力破解漏洞)
  18. 共享汽车数据分析调研案例报告
  19. [智能车]平衡车/直立车的入门经验(代码讲解)
  20. 计算机组成原理源码,计算机组成原理源码两位乘课程设计报告.docx

热门文章

  1. 可以拍c语言答案的软件下载,c语言二级考试题库app下载-C语言二级考试题库 安卓版v2.3-PC6安卓网...
  2. 2021 年前端宝典【超三百篇】
  3. 补充netty权威指南学习自定义协议实现,与springboot集成
  4. 怎样快速将图片dpi修改为300?如何调整照片分辨率?
  5. MATLAB中使用XLSREAD无法找到文件的一种解决方法
  6. 二维图像矢量化方法简述
  7. tomcat9 中文乱码
  8. 炒币之止损止盈控制的艺术、投资入门
  9. 【笔记】TAOCP Vol4 - Combination
  10. python如何循环sql语句_python sql 循环语句怎么写-问答-阿里云开发者社区-阿里云...