返回顶部
首页 > 资讯 > 后端开发 > Python >Java实现滑块拼图验证码
  • 351
分享到

Java实现滑块拼图验证码

2024-04-02 19:04:59 351人浏览 八月长安

Python 官方文档:入门教程 => 点击学习

摘要

本文实例为大家分享了Java实现滑块拼图验证码的具体代码,供大家参考,具体内容如下 1、后端随机生成抠图和带有抠图阴影的背景图片,后台保存随机抠图位置坐标 2、前端实现滑动交互,将抠

本文实例为大家分享了Java实现滑块拼图验证码的具体代码,供大家参考,具体内容如下

1、后端随机生成抠图和带有抠图阴影的背景图片,后台保存随机抠图位置坐标
2、前端实现滑动交互,将抠图拼在抠图阴影之上,获取到用户滑动距离值,比如以下示例

3、前端将用户滑动距离值传入后端,后端校验误差是否在容许范围内。

这里单纯校验用户滑动距离是最基本的校验,出于更高的安全考虑,可能还会考虑用户滑动的整个轨迹,用户在当前页面的访问行为等。这些可以很复杂,甚至借助到用户行为数据分析模型,最终的目标都是增加非法的模拟和绕过的难度。这些有机会可以再归纳总结常用到的方法,本文重点集中在如何基于Java来一步步实现滑动验证码的生成。

可以看到,滑动图形验证码,重要有两个图片组成,抠块和带有抠块阴影的原图,这里面有两个重要特性保证被暴力破解的难度:抠块的形状随机和抠块所在原图的位置随机。这样就可以在有限的图集中制造出随机的、无规律可寻的抠图和原图的配对。

用代码如何从一张大图中抠出一个有特定随机形状的小图呢?

第一步,先确定一个抠出图的轮廓,方便后续真正开始执行图片处理操作

图片是有像素组成,每个像素点对应一种颜色,颜色可以用RGB形式表示,外加一个透明度,把一张图理解成一个平面图形,左上角为原点,向右x轴,向下y轴,一个坐标值对应该位置像素点的颜色,这样就可以把一张图转换成一个二维数组。基于这个考虑,轮廓也用二维数组来表示,轮廓内元素值为1,轮廓外元素值对应0。

这时候就要想这个轮廓形状怎么生成了。有坐标系、有矩形、有圆形,没错,用到数学的图形函数。典型用到一个圆的函数方程和矩形的边线的函数,类似:

(x-a)²+(y-b)²=r²中,有三个参数a、b、r,即圆心坐标为(a,b),半径r。这些将抠图放在上文描述的坐标系上很容易就图算出来具体的值。

示例代码如下:


static int targetWidth = 55;//小图长
static int targetHeight = 45;//小图宽
static int circleR = 8;//半径
static int r1 = 4;//距离点
 
    
    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); //64
 
        double 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;
    }

第二步,有这个轮廓后就可以依据这个二维数组的值来判定抠图并在原图上抠图位置处加阴影。

操作如下:



    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 Map<String,Object> createImage(File file, Map<String,Object> resultMap){
        try {
            BufferedImage oriImage = Imageio.read(file);
            Random random = new Random();
            //X轴距离右端targetWidth  Y轴距离底部targetHeight以上
            int widthRandom = random.nextInt(oriImage.getWidth()-  2*targetWidth) + targetWidth;
            int heightRandom = random.nextInt(oriImage.getHeight()- targetHeight);
            logger.info("原图大小{} x {},随机生成的坐标 X,Y 为({},{})",oriImage.getWidth(),oriImage.getHeight(),widthRandom,heightRandom);
 
            BufferedImage targetImage= new BufferedImage(targetWidth, targetHeight, BufferedImage.TYPE_4BYTE_ABGR);
            cutByTemplate(oriImage,targetImage,getBlockData(),widthRandom,heightRandom);
 
            resultMap.put("bigImage", getImageBASE64(oriImage));//大图
            resultMap.put("smallImage", getImageBASE64(targetImage));//小图
            resultMap.put("xWidth",widthRandom);
            resultMap.put("yHeight",heightRandom);
        } catch (Exception e) {
            logger.info("创建图形验证码异常",e);
        } finally{
            return resultMap;
        }
    }
 
 
    
    public static Map<String,Object> createImage(String imgUrl, Map<String,Object> resultMap){
        try {
            //通过URL 读取图片
            URL url = new URL(imgUrl);
            BufferedImage bufferedImage = ImageIO.read(url.openStream());
            Random rand = new Random();
            int widthRandom = rand.nextInt(bufferedImage.getWidth()-  targetWidth - 100 + 1 ) + 100;
            int heightRandom = rand.nextInt(bufferedImage.getHeight()- targetHeight + 1 );
            logger.info("原图大小{} x {},随机生成的坐标 X,Y 为({},{})",bufferedImage.getWidth(),bufferedImage.getHeight(),widthRandom,heightRandom);
 
            BufferedImage target= new BufferedImage(targetWidth, targetHeight, BufferedImage.TYPE_4BYTE_ABGR);
            cutByTemplate(bufferedImage,target,getBlockData(),widthRandom,heightRandom);
            resultMap.put("bigImage", getImageBASE64(bufferedImage));//大图
            resultMap.put("smallImage", getImageBASE64(target));//小图
            resultMap.put("xWidth",widthRandom);
            resultMap.put("yHeight",heightRandom);
        } catch (Exception e) {
            logger.info("创建图形验证码异常",e);
        } finally{
            return resultMap;
        }
    }
 
 
    
    public static String getImageBASE64(BufferedImage image) throws IOException {
        byte[] imagedata = null;
        ByteArrayOutputStream bao=new ByteArrayOutputStream();
        ImageIO.write(image,"png",bao);
        imagedata=bao.toByteArray();
        BASE64Encoder encoder = new BASE64Encoder();
        String BASE64IMAGE=encoder.encodeBuffer(imagedata).trim();
        BASE64IMAGE = BASE64IMAGE.replaceAll("\r|\n", "");  //删除 \r\n
        return BASE64IMAGE;
    }

控制层代码实现及校验验证码:



    @RequestMapping(value = "/getImageVerifyCode.do", method = RequestMethod.GET, produces = {"application/JSON;charset=UTF-8"})
    public BaseRestResult getImageVerifyCode() {
        Map<String, Object> resultMap = new HashMap<>();
        //读取本地路径下的图片,随机选一条
        File file = new File(this.getClass().getResource("/image").getPath());
        File[] files = file.listFiles();
        int n = new Random().nextInt(files.length);
        File imageUrl = files[n];
        ImageUtil.createImage(imageUrl, resultMap);
 
        //读取网络图片
        //ImageUtil.createImage("/7986d66f29bfeb6015aaaec33D33fcd1d875ca16316f-2bMHNG_fw658",resultMap);
        session.setAttribute("xWidth", resultMap.get("xWidth"));
        resultMap.remove("xWidth");
        resultMap.put("errcode", 0);
        resultMap.put("errmsg", "success");
        return new BaseRestResult(resultMap);
    }
 
 
    
    @RequestMapping(value = "/verifyImageCode.do", method = RequestMethod.GET, produces = {"application/json;charset=UTF-8"})
    public BaseRestResult verifyImageCode(@RequestParam(value = "moveLength") String moveLength) {
        Double dMoveLength = Double.valueOf(moveLength);
        Map<String, Object> resultMap = new HashMap<>();
        try {
            Integer xWidth = (Integer) session.getAttribute("xWidth");
            if (xWidth == null) {
                resultMap.put("errcode", 1);
                resultMap.put("errmsg", "验证过期,请重试");
                return new BaseRestResult(resultMap);
            }
            if (Math.abs(xWidth - dMoveLength) > 10) {
                resultMap.put("errcode", 1);
                resultMap.put("errmsg", "验证不通过");
            } else {
                resultMap.put("errcode", 0);
                resultMap.put("errmsg", "验证通过");
            }
        } catch (Exception e) {
            throw new EsServiceException(e.getMessage());
        } finally {
            session.removeAttribute("xWidth");
        }
        return new BaseRestResult(resultMap);
}

前端显示图片代码:


<img src="data:image/png;base64,+返回的base64图片码" alt="抠图">
<img src="data:image/png;base64,+返回的base64图片码" alt="带抠图阴影的原图">

至此后台java实现滑块验证码关键代码完成!

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持编程网。

--结束END--

本文标题: Java实现滑块拼图验证码

本文链接: https://lsjlt.com/news/131007.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • Java实现滑块拼图验证码
    本文实例为大家分享了Java实现滑块拼图验证码的具体代码,供大家参考,具体内容如下 1、后端随机生成抠图和带有抠图阴影的背景图片,后台保存随机抠图位置坐标 2、前端实现滑动交互,将抠...
    99+
    2024-04-02
  • Python实现滑块拼图验证码详解
    目录初级版滑块拼图验证码补充知识点高级版滑动拼图验证码滑动拼图验证码可以算是滑块验证码的进阶版本,其验证机制相对复杂。本节将介绍两种滑动拼图验证码:初级版和高级版本。 初级版滑块拼...
    99+
    2024-04-02
  • Android 如何实现滑块拼图验证码功能
    本篇内容主要讲解“Android 如何实现滑块拼图验证码功能”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Android 如何实现滑块拼图验证码功能”吧!本篇主要从两方面进行介绍:使用依赖库实现...
    99+
    2023-06-14
  • vue+elementui实现拖住滑块拼图验证
    vue拖住滑块拼图验证,以下是cavas直接写的滑块拼图验证码,直接复制引用即可 ​<template>   <div id="puzzle" ref="puzz...
    99+
    2024-04-02
  • JavaScript实现拼图式滑块验证功能
    目录演示前戏源码介绍主页样式设计滑块验证部分img_ver内部演示 前戏 滑块验证码是在网站、APP等应用中常见的一种验证方式,通过按照一定规则滑动滑块到指定位置完成验证,才可以进...
    99+
    2024-04-02
  • Android 简单的实现滑块拼图验证码功能
    目录实现过程:接下来我们对这个库进行介绍:实现滑块拼图验证码功能之前已经写过一篇了,上一篇使用的是自定义控件的方式实现这个功能,主要还是想让童鞋们知其然更知其所以然,还没看的童鞋可以...
    99+
    2024-04-02
  • C#滑动验证码拼图验证功能实现(SlideCaptcha)
    目录使用背景:实现分析:后端代码:准备:使用:前端代码:结语:使用背景: 关于滑动验证码的使用场所还是非常多的,如:调取短信接口之前,和 注册请求之前 或者 频繁会调用的接口都需要加...
    99+
    2024-04-02
  • 【flutter滑动拼图验证码】
    Java后台使用aj_captcha插件,提供/captcha/get(获取captcha底图和拼块图片)、/captcha/check(验证拼图偏移量)这两个接口。并且这个插件在GitHub上有源码。 1.先准备好aj_captcha的...
    99+
    2023-08-19
    flutter
  • JavaScript如何实现拼图式滑块验证功能
    这篇文章主要介绍“JavaScript如何实现拼图式滑块验证功能”,在日常操作中,相信很多人在JavaScript如何实现拼图式滑块验证功能问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”JavaScript如...
    99+
    2023-07-02
  • JavaScript实现滑块验证码
    本文实例为大家分享了JavaScript实现滑块验证码的具体代码,供大家参考,具体内容如下 效果:鼠标在底部滑块上按下按住不松拖动可以移动滑块,上面大图里面带有小图背景的滑块也会跟随...
    99+
    2024-04-02
  • JavaScript实现拖动滑块拼图验证功能(html5、canvas)
    引言: 滑块拖动验证现在很多地方都用到,周末就琢磨着写了一个,放上来,看看有没有人用得上! 效果: 实现思路:  用一张画布绘制源图,再绘制一个填充的方形,这样就可以达到...
    99+
    2024-04-02
  • 如何在Android中实现一个滑块拼图验证码功能
    本篇文章给大家分享的是有关如何在Android中实现一个滑块拼图验证码功能,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。一、实现步骤:定义自定义属性; 2、确认目标位置,这里使...
    99+
    2023-06-06
  • vue实现登录滑动拼图验证
    本文实例为大家分享了vue实现登录滑动拼图验证的具体代码,供大家参考,具体内容如下 一、安装插件 npm install --save vue-monoplasty-slide-ve...
    99+
    2024-04-02
  • Python实现滑块验证码详解
    本节要讲解如下图所示的滑块验证码(更为复杂的滑动拼图验证码在下一篇介绍)。这种验证码机制比较简单:将滑块拖动到滑轨的最右端即可完成验证,如下图所示。如果未将滑块拖动到滑轨的最右端,则...
    99+
    2024-04-02
  • JS 简单实现滑块验证码
    目录开篇:一、实现效果styleScript二、总结与思考开篇: 拖动底部滑块,实现滑块验证码功能 一、实现效果 style *{ margin: 0; padd...
    99+
    2023-05-14
    JS 滑块验证码 JS 验证码
  • JS怎么实现滑块验证码
    本篇内容介绍了“JS怎么实现滑块验证码”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!style*{   &nb...
    99+
    2023-07-05
  • python 密码验证(滑块验证)
    目录题目描述:解题思路/算法分析/问题及解决实验代码题目描述: (1)模拟登陆界面,判别用户名和密码,给出合适的提示,如果超过三次,锁定输入。用代替密码;或者最新输入显示,前面的变成...
    99+
    2024-04-02
  • PHP如何实现滑块验证图片
    这篇文章主要讲解了“PHP如何实现滑块验证图片”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“PHP如何实现滑块验证图片”吧!安装composer require kkok...
    99+
    2023-07-04
  • 微信小程序实现滑动验证拼图
    本文实例为大家分享了微信小程序实现滑动验证拼图的具体代码,供大家参考,具体内容如下 效果图 .wxml <button bindtap="visidlisd">滑动验证...
    99+
    2024-04-02
  • OpenCV结合selenium实现滑块验证码
    本次案例使用OpenCV和selenium来解决一下滑块验证码 先说一下思路: 弹出滑块验证码后使用selenium元素截图将验证码整个背景图截取出来 将需要滑动...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作