通过比较rgb破解滑动验证码

目标url:信用中国(广东中山)行政处罚

 /**
     * base64转BufferedImage
     *
     * @param base64
     * @return
     */
    public static BufferedImage base64ToBufferedImage(String base64) {
        BufferedImage ret = null;
        try {
            Decoder decoder = Base64.getDecoder();
            ByteArrayInputStream bais = new ByteArrayInputStream(decoder.decode(base64));
            ret = ImageIO.read(bais);
            return ret;
        } catch (IOException ex) {
            Logger.getLogger(SliderUtil.class.getName()).log(Level.SEVERE, null, ex);
            return ret;
        }
    }

    /**
     * 获取滑块偏移距离和session
     *
     * @param url
     * @param session
     * @return
     * @throws IOException
     */
    public static int getDistanceAndSession(String url, StringBuffer session) throws IOException {
        int ret = -1;
        Gson gson = new Gson();
        Connection conn = Jsoup.connect(url);
        conn.method(Connection.Method.GET).timeout(10 * 1000).ignoreContentType(true).maxBodySize(0);
        Response res = conn.execute();
        //获取session
        //先清空
        session.delete(0, session.length());
        session.append(res.cookie("JSESSIONID"));
        HashMap<String, Object> hm = gson.fromJson(res.body(), HashMap.class);
        //滑块相对于原图的y坐标偏移
        int puzzleYAxis = Integer.parseInt(hm.get("puzzleYAxis").toString());
        //图片的base64字符
        String sourceBase64 = hm.get("sourceImg").toString().replace("\r\n", "");
        String puzzleBase64 = hm.get("puzzleImg").toString().replace("\r\n", "");
        //原图
        BufferedImage sourceImg = base64ToBufferedImage(sourceBase64);
        //滑块
        BufferedImage puzzleImg = base64ToBufferedImage(puzzleBase64);
        //滑块宽度
        int puzzleImgWidth = puzzleImg.getWidth();
        //滑块高度
        int puzzleImgHeight = puzzleImg.getHeight();
        //原图宽度
        int width = sourceImg.getWidth();
        //原图高度
        int height = sourceImg.getHeight();
//        //用于保存原图的rgb
//        int[] rgbArray = new int[width * height];
//        sourceImg.getRGB(0, 0, width, height, rgbArray, 0, width);
        //保存原图待对比的rgb数组
        int[] sourceImgRgbArr = new int[width * puzzleImgHeight];
        //保存滑块的rgb数组
        int[] puzzleImgRgbArr = new int[puzzleImgWidth * puzzleImgHeight];
        //将滑块的rgb复制到rgb数组中
        puzzleImg.getRGB(0, 0, puzzleImgWidth, puzzleImgHeight, puzzleImgRgbArr, 0, puzzleImgWidth);
        int k = 0;
        //截取与滑块等高的rgb数组
        for (int i = puzzleYAxis; i < puzzleYAxis + puzzleImgHeight; i++) {
            for (int j = 0; j < width; j++) {
                //获取需要对比的原图rgb数组
                sourceImgRgbArr[k++] = sourceImg.getRGB(j, i);
//                    System.out.printf("%10x", img.getRGB(j, i));
//                    System.out.println(k);
            }
//                System.out.println();
        }
        //记录当前比对的第几列
        int index = 0;
        //记录已比对的列数
        int c = 0;
        //总的比对列数
        //只要比对六列相等,就认为找到位置
        int count = 6;
        //是否找到rgb相等的值
        boolean isFind = false;
        //比对每一列的数据
        for (int i = 0; i < width; i++) {
            //记录当前比对的第几列
            index = i;
            for (int j = 0; j < puzzleImgHeight; j++) {
                //判断rgb值是否相等
                if (sourceImgRgbArr[j * width + i] != puzzleImgRgbArr[j * puzzleImgWidth + c]) {
                    //标志更新为false
                    isFind = false;
//                        System.out.println(i);
                    //重置比对的次数
                    c = 0;
                    //只要不相等就跳过此次列的比对
                    break;
                } else if (c == count && isFind) {
                    //找count次并且标志为true就算找到
                    break;
                }
                isFind = true;
//                    System.out.print(" ");
            }
            ////找count次并且标志为true就算找到,不再继续
            if (isFind && c == count) {
                break;
            }
//                System.out.println();
            //更新目前已比对的列数
            c++;
        }
        //如果找到,返回初始比对的第几列
        //后比对的第几列 - 已经比对的列数 = 初始比对的位置(即滑块的正确位置)
        if (isFind) {
            ret = index - count;
        }
        return ret;
    }

 原理:通过滑块的rgb数组与原图rgb数组进行对比。

  1.把rgb数组看成二维

  2.比对滑块rbg数组的前几列(自定义)与原图rgb数组进行循环比对

  3.只要前几列对比成功就返回初始对比列的索引

 

posted @ 2021-04-16 16:21  SirPi  阅读(139)  评论(0编辑  收藏  举报