【验证码识别】(一)京东滑块验证码爆破---获取滑块坐标 java版本

首先打开某东的网页。点击登录
【验证码识别】(一)京东滑块验证码爆破---获取滑块坐标 java版本_第1张图片
挡住我们登录的第一道防线就是这个滑块验证码了。
首先我们分析一下呗
换一张看看
【验证码识别】(一)京东滑块验证码爆破---获取滑块坐标 java版本_第2张图片
多换几张
【验证码识别】(一)京东滑块验证码爆破---获取滑块坐标 java版本_第3张图片
第一张的图片怎么又出现了
看来图库是非常有限的
那么这样的滑块图片缺口位置确定就非常的简单了
首先看下图片的请求
【验证码识别】(一)京东滑块验证码爆破---获取滑块坐标 java版本_第4张图片
非常明显就是这个请求
https://iv.jd.com/slide/g.html
下载了图片的滑块的base64编码和滑块所在纵坐标的位置y
首先我们写一个脚本将图片都下载到本地中
非常快我们下载了五百张左右的图片

可以看见基本背景已经重复的非常多了。仔细看一下某东的滑块背景仅有10张图
那么缺口位置就非常好的去定位了
我们能看到现在所有的背景图都是带缺口的
那么我们如何做到获得真正的背景图呢
这边我选择的是选两张缺口位置不一样的图各取一块然后拼接成一个完整的图片
【验证码识别】(一)京东滑块验证码爆破---获取滑块坐标 java版本_第5张图片
这样我们获得了10张原始背景图
有的朋友看到这里应该比较清楚缺口如何去定位了
就是根据同背景图的滑块图片进行逐像素对比
图片的RGB像素如果改变较大那就是滑块缺口所在的坐标了
话不多说上代码(java代码

首先我们如何确定两张图片是同一张呢

public static String getHash(BufferedImage bi) {
        int[] rgb = new int[3];
        int height = bi.getHeight();
        int miny = bi.getMinY();
        String hash_string = "";
        for (int j = miny; j < height; j++) {
            int pixel = bi.getRGB(0, j); // 下面三行代码将一个数字转换为RGB数字
            rgb[0] = (pixel & 0xff0000) >> 16;
            rgb[1] = (pixel & 0xff00) >> 8;
            rgb[2] = (pixel & 0xff);
            hash_string += rgb[0];
            hash_string += rgb[1];
            hash_string += rgb[2];
        }
        return DigestUtils.md5Hex(hash_string);
    }

获取图片首位像素的字符串和的MD5值
如果相同则在这个场景下基本能确定是同个图片

private static String[] picStrings = {
            "0cafdec4d059a547d9b515132dfeda9c.png",
            "2e752832dd5775fb9b85ac539c21edb3.png",
            "5d2a20ff27057c1dc919c3546a015773.png",
            "6bc516221904aac0638a49e593961bd7.png",
            "18d2593513d903c71ca604f896b9163b.png",
            "9803b41933ddf82d222462237e4c9bb3.png",
            "67010e410cdaf071b5bf72fa35c1d448.png",
            "c3d0065ead7e43da9c057c81137d419e.png",
            "6c26390570b6062d423bc05e45898cbb.png",
            "c20fdaa0906d123629bade0e436903ce.png"};

    public static Map getBufferedImageMap() {
        if (bufferedImageMap == null) {
            BufferedImage bi = null;
            InputStream in = null;
            bufferedImageMap = new HashMap<>();
            for (int i = 0; i < picStrings.length; i++) {
                try {
                    in = JdSlideEncrypt.class.getClassLoader().getResourceAsStream("jdPicData/" + picStrings[i]);
                    bi = ImageIO.read(in);
                } catch (Exception e) {
                    LOG.error("bufferedImageMap创建出现异常" + e);
                }
                bufferedImageMap.put(getHash(bi), bi);
            }
            try {
                if (in != null) {
                    in.close();
                }
            } catch (Exception e) {
                LOG.error("bufferedImageMap创建出现异常" + e);
            }
        }
        return bufferedImageMap;
    }

获取所有背景图片仓库
然后就是最重要的一步了
逐像素对比

public static int parseCaptcha(BufferedImage currentBi, Map bufferedImageMap, String y) {
        int x = 0;
        int width = currentBi.getWidth();
        String hashcode = JdPicDateUtils.getHash(currentBi);
        BufferedImage baseBi = bufferedImageMap.get(hashcode);
        if (baseBi == null) {
            return 0;
        }
        int[] currentRgb = new int[3];
        int[] baseRgb = new int[3];
        int currentY = Integer.parseInt(y);
        for (int j = 0; j < width; j++) {
            int currentPixel = currentBi.getRGB(j, currentY + 20); // 下面三行代码将一个数字转换为RGB数字
            int basePixel = baseBi.getRGB(j, currentY + 20); // 下面三行代码将一个数字转换为RGB数字
            currentRgb[0] = (currentPixel & 0xff0000) >> 16;
            currentRgb[1] = (currentPixel & 0xff00) >> 8;
            currentRgb[2] = (currentPixel & 0xff);
            baseRgb[0] = (basePixel & 0xff0000) >> 16;
            baseRgb[1] = (basePixel & 0xff00) >> 8;
            baseRgb[2] = (basePixel & 0xff);
            if (Math.abs(baseRgb[0] - currentRgb[0]) + Math.abs(baseRgb[1] - currentRgb[1]) + Math.abs(baseRgb[2] - currentRgb[2]) > 50) {
                x = j;
                break;
            }
        }
        return x;
    }

如果找到就返回X
大功告成啦
并且带着大家去一步一步解析某东滑块JS代码
jd滑块第二集
https://blog.csdn.net/cyz52/article/details/102170870

代码在git上,如果有帮助到你,欢迎start
github地址
本文章纯属技术探讨学习
防止不法用途
轨迹代码为旧版本需要自行优化

有任何问题可以联系邮箱[email protected]

你可能感兴趣的:(滑块验证码,java)