精华内容
下载资源
问答
  • 【验证码识别】OpenCV挑战腾讯防水墙滑动验证码

    万次阅读 多人点赞 2021-01-04 18:22:43
    使用java + selenium + OpenCV破解腾讯防水墙滑动验证码 戳这里→康康你手机号在过多少网站注册过!!! 友情推荐:新一代安全短信 * 验证码地址:https://007.qq.com/online.html * 使用OpenCv模板匹配 * 成功率90%...

    使用 OpenCV破解腾讯防水墙滑动验证码

    戳这里→康康你手机号在过多少网站注册过!!!
    友情推荐:新一代安全短信

    * 验证码地址:https://007.qq.com/online.html
    * 使用OpenCv模板匹配
    * 成功率90%左右
    * Java + Selenium + OpenCV
    

    产品样例
    腾讯防水墙
    来吧!展示!

    结果展示
    注意!!!
    · 在模拟滑动时不能按照相同速度或者过快的速度滑动,需要向人滑动时一样先快后慢,这样才不容易被识别。
    模拟滑动代码↓↓↓

    /**
    	 * 模拟人工移动
    	 * @param driver
    	 * @param element页面滑块
    	 * @param distance需要移动距离
    	 */
    	public static void move(WebDriver driver, WebElement element, int distance) throws InterruptedException {
    		int randomTime = 0;
    		if (distance > 90) {
    			randomTime = 250;
    		} else if (distance > 80 && distance <= 90) {
    			randomTime = 150;
    		}
    		List<Integer> track = getMoveTrack(distance - 2);
    		int moveY = 1;
    		try {
    			Actions actions = new Actions(driver);
    			actions.clickAndHold(element).perform();
    			Thread.sleep(200);
    			for (int i = 0; i < track.size(); i++) {
    				actions.moveByOffset(track.get(i), moveY).perform();
    				Thread.sleep(new Random().nextInt(300) + randomTime);
    			}
    			Thread.sleep(200);
    			actions.release(element).perform();
    		} catch (Exception e) {
    			e.printStackTrace();
    		}
    	}
    	/**
    	 * 根据距离获取滑动轨迹
    	 * @param distance需要移动的距离
    	 * @return
    	 */
    	public static List<Integer> getMoveTrack(int distance) {
    		List<Integer> track = new ArrayList<>();// 移动轨迹
    		Random random = new Random();
    		int current = 0;// 已经移动的距离
    		int mid = (int) distance * 4 / 5;// 减速阈值
    		int a = 0;
    		int move = 0;// 每次循环移动的距离
    		while (true) {
    			a = random.nextInt(10);
    			if (current <= mid) {
    				move += a;// 不断加速
    			} else {
    				move -= a;
    			}
    			if ((current + move) < distance) {
    				track.add(move);
    			} else {
    				track.add(distance - current);
    				break;
    			}
    			current += move;
    		}
    		return track;
    	}
    

    看操作,no bb,直接上代码

    private final String INDEX_URL = "https://007.qq.com/online.html?ADTAG=index.head";
    private void seleniumTest() {
    		ChromeDriverManager manager = ChromeDriverManager.getInstance();
    		int status = -1;
    		try {
    			WebDriver driver = manager.getDriver();
    			driver.get(INDEX_URL);
    			driver.manage().window().maximize(); // 设置浏览器窗口最大化
    			Thread.sleep(10000);
    			driver.findElement(By.className("wp-onb-tit")).findElements(By.tagName("a")).get(1).click();
    			Thread.sleep(500);
    			// 点击出现滑动图
    			waitWebElement(driver, By.id("code"), 500).click();
    			Thread.sleep(100);
    			// 获取到验证区域
    			driver.switchTo().frame(waitWebElement(driver, By.id("tcaptcha_iframe"), 500));
    			Thread.sleep(100);
    			// 获取滑动按钮
    			WebElement moveElemet = waitWebElement(driver, By.id("tcaptcha_drag_button"), 500);
    			Thread.sleep(100);
    			// 获取带阴影的背景图
    			String bgUrl = waitWebElement(driver, By.id("slideBg"), 500).getAttribute("src");
    			Thread.sleep(100);
    			// 获取带阴影的小图
    			String sUrl = waitWebElement(driver, By.id("slideBlock"), 500).getAttribute("src");
    			Thread.sleep(100);
    			// 获取高度
    			String topStr = waitWebElement(driver, By.id("slideBlock"), 500).getAttribute("style").substring(32, 36);
    			int top = Integer.parseInt(topStr.substring(0, topStr.indexOf("p"))) * 2;
    			Thread.sleep(100);
    			// 计算移动距离
    			int distance = (int) Double.parseDouble(getTencentDistance(bgUrl, sUrl, top));
    			// 滑动
    			move(driver, moveElemet, distance);
    			Thread.sleep(5000);
    
    		} catch (Exception e) {
    			e.printStackTrace();
    		} finally {
    			manager.closeDriver(status);
    		}
    	}
    
    	/**
    	 * 获取腾讯验证滑动距离
    	 * 
    	 * @return
    	 */
    	public static String dllPath = "C://chrome//opencv_java440.dll";
    
    	public String getTencentDistance(String bUrl, String sUrl, int top) {
    		System.load(dllPath);
    		File bFile = new File("C:/qq_b.jpg");
    		File sFile = new File("C:/qq_s.jpg");
    		try {
    			FileUtils.copyURLToFile(new URL(bUrl), bFile);
    			FileUtils.copyURLToFile(new URL(sUrl), sFile);
    			BufferedImage bgBI = ImageIO.read(bFile);
    			BufferedImage sBI = ImageIO.read(sFile);
    			// 裁剪
    			bgBI = bgBI.getSubimage(360, top, bgBI.getWidth() - 370, sBI.getHeight());
    			ImageIO.write(bgBI, "png", bFile);
    			Mat s_mat = Imgcodecs.imread(sFile.getPath());
    			Mat b_mat = Imgcodecs.imread(bFile.getPath());
    			// 转灰度图像
    			Mat s_newMat = new Mat();
    			Imgproc.cvtColor(s_mat, s_newMat, Imgproc.COLOR_BGR2GRAY);
    			// 二值化图像
    			binaryzation(s_newMat);
    			Imgcodecs.imwrite(sFile.getPath(), s_newMat);
    
    			int result_rows = b_mat.rows() - s_mat.rows() + 1;
    			int result_cols = b_mat.cols() - s_mat.cols() + 1;
    			Mat g_result = new Mat(result_rows, result_cols, CvType.CV_32FC1);
    			Imgproc.matchTemplate(b_mat, s_mat, g_result, Imgproc.TM_SQDIFF); // 归一化平方差匹配法
    			// 归一化相关匹配法
    			Core.normalize(g_result, g_result, 0, 1, Core.NORM_MINMAX, -1, new Mat());
    			Point matchLocation = new Point();
    			MinMaxLocResult mmlr = Core.minMaxLoc(g_result);
    			matchLocation = mmlr.maxLoc; // 此处使用maxLoc还是minLoc取决于使用的匹配算法
    			Imgproc.rectangle(b_mat, matchLocation,
    					new Point(matchLocation.x + s_mat.cols(), matchLocation.y + s_mat.rows()), new Scalar(0, 0, 0, 0));
    			return "" + ((matchLocation.x + s_mat.cols() + 360 - sBI.getWidth() - 46) / 2);
    		} catch (Throwable e) {
    			e.printStackTrace();
    			return null;
    		} finally {
    			bFile.delete();
    			sFile.delete();
    		}
    	}
    /**
    	 * 
    	 * @param mat
    	 *            二值化图像
    	 */
    	public static void binaryzation(Mat mat) {
    		int BLACK = 0;
    		int WHITE = 255;
    		int ucThre = 0, ucThre_new = 127;
    		int nBack_count, nData_count;
    		int nBack_sum, nData_sum;
    		int nValue;
    		int i, j;
    		int width = mat.width(), height = mat.height();
    		// 寻找最佳的阙值
    		while (ucThre != ucThre_new) {
    			nBack_sum = nData_sum = 0;
    			nBack_count = nData_count = 0;
    
    			for (j = 0; j < height; ++j) {
    				for (i = 0; i < width; i++) {
    					nValue = (int) mat.get(j, i)[0];
    
    					if (nValue > ucThre_new) {
    						nBack_sum += nValue;
    						nBack_count++;
    					} else {
    						nData_sum += nValue;
    						nData_count++;
    					}
    				}
    			}
    			nBack_sum = nBack_sum / nBack_count;
    			nData_sum = nData_sum / nData_count;
    			ucThre = ucThre_new;
    			ucThre_new = (nBack_sum + nData_sum) / 2;
    		}
    		// 二值化处理
    		int nBlack = 0;
    		int nWhite = 0;
    		for (j = 0; j < height; ++j) {
    			for (i = 0; i < width; ++i) {
    				nValue = (int) mat.get(j, i)[0];
    				if (nValue > ucThre_new) {
    					mat.put(j, i, WHITE);
    					nWhite++;
    				} else {
    					mat.put(j, i, BLACK);
    					nBlack++;
    				}
    			}
    		}
    		// 确保白底黑字
    		if (nBlack > nWhite) {
    			for (j = 0; j < height; ++j) {
    				for (i = 0; i < width; ++i) {
    					nValue = (int) (mat.get(j, i)[0]);
    					if (nValue == 0) {
    						mat.put(j, i, WHITE);
    					} else {
    						mat.put(j, i, BLACK);
    					}
    				}
    			}
    		}
    	}
    	// 延时加载
    	private static WebElement waitWebElement(WebDriver driver, By by, int count) throws Exception {
    		WebElement webElement = null;
    		boolean isWait = false;
    		for (int k = 0; k < count; k++) {
    			try {
    				webElement = driver.findElement(by);
    				if (isWait)
    					System.out.println(" ok!");
    				return webElement;
    			} catch (org.openqa.selenium.NoSuchElementException ex) {
    				isWait = true;
    				if (k == 0)
    					System.out.print("waitWebElement(" + by.toString() + ")");
    				else
    					System.out.print(".");
    				Thread.sleep(50);
    			}
    		}
    		if (isWait)
    			System.out.println(" outTime!");
    		return null;
    	}
    

    在这里插入图片描述
    戳这里→康康你手机号在过多少网站注册过!!!
    友情推荐:新一代安全短信

    相关阅读
    谷歌图形验证码在AI 面前已经形同虚设,所以谷歌宣布退出验证码服务, 那么当所有的图形验证码都被破解时
    《腾讯防水墙滑动拼图验证码》
    《百度旋转图片验证码》
    《网易易盾滑动拼图验证码》
    《顶象区域面积点选验证码》
    《顶象滑动拼图验证码》
    《极验滑动拼图验证码》
    《使用深度学习来破解 captcha 验证码》
    《验证码终结者-基于CNN+BLSTM+CTC的训练部署套件》

    展开全文
  • 使用java + selenium + OpenCV破解网易易盾滑动验证码 戳这里→康康你手机号在过多少网站注册过!!! 友情推荐:新一代安全短信 谷歌图形验证码在AI 面前已经形同虚设,所以谷歌宣布退出验证码服务, 那么当所有的...

    使用java + selenium + OpenCV破解网易易盾滑动验证码

    戳这里→康康你手机号在过多少网站注册过!!!
    友情推荐:新一代安全短信

    谷歌图形验证码在AI 面前已经形同虚设,所以谷歌宣布退出验证码服务, 那么当所有的图形验证码都被破解时
    《腾讯防水墙滑动拼图验证码》
    《百度旋转图片验证码》
    《网易易盾滑动拼图验证码》
    《顶象区域面积点选验证码》
    《顶象滑动拼图验证码》
    《极验滑动拼图验证码》
    《使用深度学习来破解 captcha 验证码》
    《验证码终结者-基于CNN+BLSTM+CTC的训练部署套件》

    * 验证码地址:https://dun.163.com/trial/jigsaw
    * 使用OpenCv模板匹配
    * Java + Selenium + OpenCV
    

    产品样例
    在这里插入图片描述
    在这里插入图片描述
    接下来就是见证奇迹的时刻!
    在这里插入图片描述

    在这里插入图片描述
    注意!!!
    · 在模拟滑动时不能按照相同速度或者过快的速度滑动,需要向人滑动时一样先快后慢,这样才不容易被识别。
    模拟滑动代码↓↓↓

    /**
    	 * 模拟人工移动
    	 * @param driver
    	 * @param element页面滑块
    	 * @param distance需要移动距离
    	 */
    	public static void move(WebDriver driver, WebElement element, int distance) throws InterruptedException {
    		int randomTime = 0;
    		if (distance > 90) {
    			randomTime = 250;
    		} else if (distance > 80 && distance <= 90) {
    			randomTime = 150;
    		}
    		List<Integer> track = getMoveTrack(distance - 2);
    		int moveY = 1;
    		try {
    			Actions actions = new Actions(driver);
    			actions.clickAndHold(element).perform();
    			Thread.sleep(200);
    			for (int i = 0; i < track.size(); i++) {
    				actions.moveByOffset(track.get(i), moveY).perform();
    				Thread.sleep(new Random().nextInt(300) + randomTime);
    			}
    			Thread.sleep(200);
    			actions.release(element).perform();
    		} catch (Exception e) {
    			e.printStackTrace();
    		}
    	}
    	/**
    	 * 根据距离获取滑动轨迹
    	 * @param distance需要移动的距离
    	 * @return
    	 */
    	public static List<Integer> getMoveTrack(int distance) {
    		List<Integer> track = new ArrayList<>();// 移动轨迹
    		Random random = new Random();
    		int current = 0;// 已经移动的距离
    		int mid = (int) distance * 4 / 5;// 减速阈值
    		int a = 0;
    		int move = 0;// 每次循环移动的距离
    		while (true) {
    			a = random.nextInt(10);
    			if (current <= mid) {
    				move += a;// 不断加速
    			} else {
    				move -= a;
    			}
    			if ((current + move) < distance) {
    				track.add(move);
    			} else {
    				track.add(distance - current);
    				break;
    			}
    			current += move;
    		}
    		return track;
    	}
    

    操作过程

    在这里插入图片描述

    /**
    	 * 获取网易验证滑动距离
    	 * 
    	 * @return
    	 */
    	public static String dllPath = "C://chrome//opencv_java440.dll";
    
    	public double getDistance(String bUrl, String sUrl) {
    		System.load(dllPath);
    		File bFile = new File("C:/EasyDun_b.png");
    		File sFile = new File("C:/EasyDun_s.png");
    		try {
    			FileUtils.copyURLToFile(new URL(bUrl), bFile);
    			FileUtils.copyURLToFile(new URL(sUrl), sFile);
    			BufferedImage bgBI = ImageIO.read(bFile);
    			BufferedImage sBI = ImageIO.read(sFile);
    			// 裁剪
    			cropImage(bgBI, sBI, bFile, sFile);
    			Mat s_mat = Imgcodecs.imread(sFile.getPath());
    			Mat b_mat = Imgcodecs.imread(bFile.getPath());
    			
    			//阴影部分为黑底时需要转灰度和二值化,为白底时不需要
    			// 转灰度图像
    			Mat s_newMat = new Mat();
    			Imgproc.cvtColor(s_mat, s_newMat, Imgproc.COLOR_BGR2GRAY);
    			// 二值化图像
    			binaryzation(s_newMat);
    			Imgcodecs.imwrite(sFile.getPath(), s_newMat);
    
    			int result_rows = b_mat.rows() - s_mat.rows() + 1;
    			int result_cols = b_mat.cols() - s_mat.cols() + 1;
    			Mat g_result = new Mat(result_rows, result_cols, CvType.CV_32FC1);
    			Imgproc.matchTemplate(b_mat, s_mat, g_result, Imgproc.TM_SQDIFF); // 归一化平方差匹配法TM_SQDIFF 相关系数匹配法TM_CCOEFF
    																				
    			Core.normalize(g_result, g_result, 0, 1, Core.NORM_MINMAX, -1, new Mat());
    			Point matchLocation = new Point();
    			MinMaxLocResult mmlr = Core.minMaxLoc(g_result);
    			matchLocation = mmlr.maxLoc; // 此处使用maxLoc还是minLoc取决于使用的匹配算法
    			Imgproc.rectangle(b_mat, matchLocation, new Point(matchLocation.x + s_mat.cols(), matchLocation.y + s_mat.rows()), new Scalar(0, 255, 0, 0));
    			Imgcodecs.imwrite(bFile.getPath(), b_mat);
    			return matchLocation.x + s_mat.cols() - sBI.getWidth() + 12;
    		} catch (Throwable e) {
    			e.printStackTrace();
    			return 0;
    		} finally {
    			 bFile.delete();
    			 sFile.delete();
    		}
    	}
    
    	/**
    	 * 图片亮度调整
    	 * 
    	 * @param image
    	 * @param param
    	 * @throws IOException
    	 */
    	public void bloding(BufferedImage image, int param) throws IOException {
    		if (image == null) {
    			return;
    		} else {
    			int rgb, R, G, B;
    			for (int i = 0; i < image.getWidth(); i++) {
    				for (int j = 0; j < image.getHeight(); j++) {
    					rgb = image.getRGB(i, j);
    					R = ((rgb >> 16) & 0xff) - param;
    					G = ((rgb >> 8) & 0xff) - param;
    					B = (rgb & 0xff) - param;
    					rgb = ((clamp(255) & 0xff) << 24) | ((clamp(R) & 0xff) << 16) | ((clamp(G) & 0xff) << 8) | ((clamp(B) & 0xff));
    					image.setRGB(i, j, rgb);
    
    				}
    			}
    		}
    	}
    
    	// 判断a,r,g,b值,大于256返回256,小于0则返回0,0到256之间则直接返回原始值
    	private int clamp(int rgb) {
    		if (rgb > 255)
    			return 255;
    		if (rgb < 0)
    			return 0;
    		return rgb;
    	}
    
    	/**
    	 * 生成半透明小图并裁剪
    	 * 
    	 * @param image
    	 * @return
    	 */
    	private void cropImage(BufferedImage bigImage, BufferedImage smallImage, File bigFile, File smallFile) {
    		int y = 0;
    		int h_ = 0;
    		try {
    			// 2 生成半透明图片
    			bloding(bigImage, 75);
    			for (int w = 0; w < smallImage.getWidth(); w++) {
    				for (int h = smallImage.getHeight() - 2; h >= 0; h--) {
    					int rgb = smallImage.getRGB(w, h);
    					int A = (rgb & 0xFF000000) >>> 24;
    					if (A >= 100) {
    						rgb = (127 << 24) | (rgb & 0x00ffffff);
    						smallImage.setRGB(w, h, rgb);
    					}
    				}
    			}
    			for (int h = 1; h < smallImage.getHeight(); h++) {
    				for (int w = 1; w < smallImage.getWidth(); w++) {
    					int rgb = smallImage.getRGB(w, h);
    					int A = (rgb & 0xFF000000) >>> 24;
    					if (A > 0) {
    						if (y == 0)
    							y = h;
    						h_ = h - y;
    						break;
    					}
    				}
    			}
    			smallImage = smallImage.getSubimage(0, y, smallImage.getWidth(), h_);
    			bigImage = bigImage.getSubimage(0, y, bigImage.getWidth(), h_);
    			ImageIO.write(bigImage, "png", bigFile);
    			ImageIO.write(smallImage, "png", smallFile);
    		} catch (Throwable e) {
    			System.out.println(e.toString());
    		}
    	}
    
    	/**
    	 * 
    	 * @param mat
    	 *            二值化图像
    	 */
    	public static void binaryzation(Mat mat) {
    		int BLACK = 0;
    		int WHITE = 255;
    		int ucThre = 0, ucThre_new = 127;
    		int nBack_count, nData_count;
    		int nBack_sum, nData_sum;
    		int nValue;
    		int i, j;
    		int width = mat.width(), height = mat.height();
    		// 寻找最佳的阙值
    		while (ucThre != ucThre_new) {
    			nBack_sum = nData_sum = 0;
    			nBack_count = nData_count = 0;
    
    			for (j = 0; j < height; ++j) {
    				for (i = 0; i < width; i++) {
    					nValue = (int) mat.get(j, i)[0];
    
    					if (nValue > ucThre_new) {
    						nBack_sum += nValue;
    						nBack_count++;
    					} else {
    						nData_sum += nValue;
    						nData_count++;
    					}
    				}
    			}
    			nBack_sum = nBack_sum / nBack_count;
    			nData_sum = nData_sum / nData_count;
    			ucThre = ucThre_new;
    			ucThre_new = (nBack_sum + nData_sum) / 2;
    		}
    		// 二值化处理
    		int nBlack = 0;
    		int nWhite = 0;
    		for (j = 0; j < height; ++j) {
    			for (i = 0; i < width; ++i) {
    				nValue = (int) mat.get(j, i)[0];
    				if (nValue > ucThre_new) {
    					mat.put(j, i, WHITE);
    					nWhite++;
    				} else {
    					mat.put(j, i, BLACK);
    					nBlack++;
    				}
    			}
    		}
    		// 确保白底黑字
    		if (nBlack > nWhite) {
    			for (j = 0; j < height; ++j) {
    				for (i = 0; i < width; ++i) {
    					nValue = (int) (mat.get(j, i)[0]);
    					if (nValue == 0) {
    						mat.put(j, i, WHITE);
    					} else {
    						mat.put(j, i, BLACK);
    					}
    				}
    			}
    		}
    	}
    	// 延时加载
    	private static WebElement waitWebElement(WebDriver driver, By by, int count) throws Exception {
    		WebElement webElement = null;
    		boolean isWait = false;
    		for (int k = 0; k < count; k++) {
    			try {
    				webElement = driver.findElement(by);
    				if (isWait)
    					System.out.println(" ok!");
    				return webElement;
    			} catch (org.openqa.selenium.NoSuchElementException ex) {
    				isWait = true;
    				if (k == 0)
    					System.out.print("waitWebElement(" + by.toString() + ")");
    				else
    					System.out.print(".");
    				Thread.sleep(50);
    			}
    		}
    		if (isWait)
    			System.out.println(" outTime!");
    		return null;
    	}
    

    注意:有一个问题还没有解决,还无法区分阴影部分是黑色还是白色。 因为两种的情况不同,所以处理方式也不同。阴影部分为黑底时需要转灰度和二值化,为白底时不需要。黑底使用归一化平方差匹配算法 TM_SQDIFF ,而白底使用相关系数匹配算法 TM_CCOEFF。

    有找到区分方法的大佬可以私信作者或者在评论区留言哦。

    在这里插入图片描述
    戳这里→康康你手机号在过多少网站注册过!!!
    友情推荐:新一代安全短信

    展开全文
  • 话不多说直接上效果图 ...滑动验证 页面源码 <template> <div id="loginWrap"> <div id="loginArea"> <!--<el-tooltip class="item" effect="dark" :content="$t('login.ch...

    话不多说直接上效果图

    vue 注册首页

    校验

    滑动验证

     

    页面源码

    <template>
      <div id="loginWrap">
        <div id="loginArea">
          <!--<el-tooltip class="item" effect="dark" :content="$t('login.change')" placement="bottom-end">-->
          <!--<i class="exChange el-icon-fa-exchange" @click="exChange"></i>-->
          <!--</el-tooltip>-->
          <div class="loginPanel regPanel">
            <h1><img src="../../assets/css/theme1/images/logo.png"/>{{$t('login.title')}}</h1>
            <div class="login">
              <div class="province">
                <h2>注册</h2>
                <!--<lang-select class="set-language"></lang-select>-->
              </div>
              <div class="form-group">
                <el-form  class="loginFrom" :model="ruleForm" :rules="rules" ref="ruleForm" label-width="100px" >
    
                  <!--登录名-->
                  <el-form-item prop="userName" label-width="0px">
                    <i class="fa el-icon-fa-user-o"></i>
                    <el-input type="text" :placeholder="$t('login.username')" name="userName" v-model.trim="ruleForm.userName" autoComplete="on"  @keyup.enter.native="submitButton" clearable></el-input>
                  </el-form-item>
                  <!--手机号-->
                  <el-form-item prop="tel" label-width="0px">
                    <i class="fa el-icon-fa-mobile-phone"></i>
                    <el-input type="tel"  :placeholder="$t('login.tel')" name="tel" v-model.trim="ruleForm.tel" autoComplete="on"  @keyup.enter.native="submitButton" clearable></el-input>
                  </el-form-item>
                  <!--验证码-->
                  <el-row :gutter="10">
                    <el-col :span="17">
                      <el-form-item prop="smscode" label-width="0px">
                        <i class="fa el-icon-fa-envelope-o"></i>
                        <el-input    type="smscode" ref="smscode" :placeholder="$t('login.smscode')" name="smscode" v-model.trim="ruleForm.smscode" autoComplete="on"  @keyup.enter.native="submitButton" clearable></el-input>
                      </el-form-item>
                    </el-col>
                    <el-col :span="7">
                      <!--发送验证码-->
                      <el-button class="loginBtn codeBtn" type="primary" :disabled='isDisabled' @click="sendCode">{{buttonText}}</el-button>
                    </el-col>
                  </el-row>
                  <!--公司名称-->
                  <el-form-item prop="companyname" label-width="0px">
                    <i class="fa el-icon-fa-home"></i>
                    <el-input type="text" ref="pass" :placeholder="$t('login.companyname')" name="companyname" v-model="ruleForm.companyname" autoComplete="on" clearable></el-input>
                  </el-form-item>
                  <!--联系人-->
                  <el-form-item prop="contactperson" label-width="0px">
                    <i class="fa el-icon-fa-address-book-o"></i>
                    <el-input type="contactperson" ref="pass" :placeholder="$t('login.contactperson')" name="contactperson" v-model="ruleForm.contactperson" autoComplete="on" clearable></el-input>
                  </el-form-item>
                  <!--Emaill-->
                  <el-form-item prop="email" label-width="0px">
                    <i class="fa el-icon-fa-envelope"></i>
                    <el-input type="email" ref="pass" :placeholder="$t('login.email')" name="email" v-model="ruleForm.email" autoComplete="on"  clearable></el-input>
                  </el-form-item>
                  <!--密码-->
                  <el-form-item prop="password" label-width="0px">
                    <i class="fa el-icon-fa-lock"></i>
                    <el-input type="password" ref="pass" :placeholder="$t('login.password')" name="password" v-model.trim="ruleForm.password" autoComplete="on"  @keyup.enter.native="submitButton" clearable></el-input>
                  </el-form-item>
                  <!--确认密码-->
                  <el-form-item prop="checkpassword" label-width="0px">
                    <i class="fa el-icon-fa-lock"></i>
                    <el-input type="password" ref="pass" :placeholder="$t('login.checkpassword')" name="checkpassword" v-model.trim="ruleForm.checkpassword" autoComplete="on"  @keyup.enter.native="submitButton" clearable></el-input>
                  </el-form-item>
                  <el-button class="loginBtn" type="primary" :loading="logining" v-popover:popover  @click="submitButton" >{{$t('login.submit')}}</el-button>
    
                  <el-form-item label-width="0px" class="serverSel" v-if="serverVis">
                    <i class="fa el-icon-fa-database"></i>
                    <el-select v-model="server" popper-class="serverSelList" filterable placeholder="跳转至分服务器" @change="handlerServer">
                      <el-option  v-for="item in serverOptions"  :key="item.value"  :label="item.label"  :value="item.value">
                      </el-option>
                    </el-select>
                  </el-form-item>
                </el-form>
              </div>
              <!--验证码弹窗-->
              <el-popover  popper-class="slidingPictures"  ref="popover"  trigger="manual" v-model="visible"  >
                <div class="sliding-pictures">
                  <div class="vimg">
                    <canvas id="sliderBlock"></canvas>
                    <canvas id="codeImg"></canvas>
                  </div>
                  <div class="slider">
                    <div class="track" :class="{pintuTrue: puzzle }">
                      {{ tips }}
                    </div>
                    <div class="button el-icon-s-grid" @mousedown.prevent="drag"></div>
                  </div>
                  <div class="operation">
                    <span title="关闭验证码"  @click="visible = false"   class="el-icon-circle-close" ></span>
                    <span title="刷新验证码"  @click="canvasInit"  class="el-icon-refresh-left" ></span>
                  </div>
                </div>
              </el-popover>
              <div class="tips">
                <span style="cursor: pointer;" @click="toLogin()">已有账号,返回登录</span>
              </div>
            </div>
          </div>
        </div>
      </div>
    </template>

     

    点击确认调用方法

    <el-button class="loginBtn" type="primary" :loading="logining" v-popover:popover  @click="submitButton" >{{$t('login.submit')}}</el-button>

    确认按钮方法

    // 确认按钮
    submitButton () {
      this.$refs['ruleForm'].validate(valid => {
        if (valid) {
          this.visible = true
          this.puzzle = false
          this.tips = '拖动左边滑块完成上方拼图'
        }
      })
    },

    全部源码下载链接

    https://download.csdn.net/download/she8656837/11988753

    展开全文
  • selenium + Chrome 解决滑动验证码

    万次阅读 2019-09-06 15:24:51
    具体详情见代码,研究网站很简单,就是输入手机号点击获取验证码,就会弹出滑动验证码这种 在自己写代码前参考了一批博客,是把所有验证码图片截取所有验证码图片保存在本地,再对比,感觉方法不行,所以自己写了个...

    声明:文章仅源自个人兴趣爱好,不涉及他用,侵权联系删。

     

    具体详情见代码,研究网站很简单,就是输入手机号点击获取验证码,就会弹出滑动验证码这种

    在自己写代码前参考了一批博客,是把所有验证码图片截取所有验证码图片保存在本地,再对比,感觉方法不行,所以自己写了个破解方法,通过js修改css直接抓取完整图片,因为上一篇写了B站,这里就不一一分析了,直接上代码:

    完整代码:

     

    # -*- coding:utf-8 -*-
    '''
    研究网站:  https://account.ch.com/NonRegistrations-Regist
    滑块验证码也分两种:
        1.直接给缺口图片,先滑动到缺口找到完整验证码图片,对比有缺口的验证码图片,然后计算缺口坐标,再利用selenium移动按钮到指定位置
    
        2.直接给原图,缺口需要点击出现,直接保存原图,然后对比
    '''
    from selenium import webdriver
    from selenium.webdriver.support.wait import WebDriverWait
    from selenium.webdriver.support import expected_conditions as EC
    from selenium.webdriver.common.by import By
    from selenium.webdriver import ActionChains
    from lxml.html import etree
    from PIL import Image
    from time import sleep
    import re, requests
    from urllib.request import urlretrieve
    from bs4 import BeautifulSoup
    
    class SliderVerificationCode(object):
        def __init__(self):  # 初始化一些信息
            self.left = 60  # 定义一个左边的起点 缺口一般离图片左侧有一定的距离 有一个滑块
            self.url = 'https://account.ch.com/NonRegistrations-Regist'
            self.chromedriverPath = "C:\Program Files (x86)\Google\Chrome\Application\chromedriver.exe"
            self.driver = webdriver.Chrome(executable_path=self.chromedriverPath)
            self.wait = WebDriverWait(self.driver, 20)  # 设置等待时间20秒
            self.phone = "18516544488"
    
        def input_name_password(self):  # 输入手机号
            self.driver.get(self.url)
            self.driver.maximize_window()
            self.inputphone = self.wait.until(EC.presence_of_element_located((By.NAME, 'phoneNumberInput')))
            self.inputphone.send_keys(self.phone)
    
    
        def click_login_button(self):  # 点击登录按钮,出现验证码图片
            login_button = self.wait.until(EC.element_to_be_clickable((By.ID, 'getDynamicPwd')))
            login_button.click()
            sleep(1)
    
        def get_geetest_image(self):  # 获取验证码图片
            # print(self.driver.page_source)
            gapimg = self.wait.until(EC.presence_of_element_located((By.CLASS_NAME, 'geetest_canvas_bg')))
            sleep(2)
            gapimg.screenshot(r'./captcha1.png')
            # 通过js代码修改标签样式 显示图片2
            js = 'var change = document.getElementsByClassName("geetest_canvas_fullbg");change[0].style = "display:block;"'
            self.driver.execute_script(js)
            sleep(2)
            fullimg = self.wait.until(
                EC.presence_of_element_located((By.CLASS_NAME, 'geetest_canvas_fullbg')))
            fullimg.screenshot(r'./captcha2.png')
    
        def is_similar(self, image1, image2, x, y):
            '''判断两张图片 各个位置的像素是否相同
            #image1:带缺口的图片
            :param image2: 不带缺口的图片
            :param x: 位置x
            :param y: 位置y
            :return: (x,y)位置的像素是否相同
            '''
            # 获取两张图片指定位置的像素点
            pixel1 = image1.load()[x, y]
            pixel2 = image2.load()[x, y]
            # 设置一个阈值 允许有误差
            threshold = 60
            # 彩色图 每个位置的像素点有三个通道
            if abs(pixel1[0] - pixel2[0]) < threshold and abs(pixel1[1] - pixel2[1]) < threshold and abs(
                    pixel1[2] - pixel2[2]) < threshold:
                return True
            else:
                return False
    
        def get_diff_location(self):  # 获取缺口图起点
            captcha1 = Image.open('captcha1.png')
            captcha2 = Image.open('captcha2.png')
            for x in range(self.left, captcha1.size[0]):  # 从左到右 x方向
                for y in range(captcha1.size[1]):  # 从上到下 y方向
                    if not self.is_similar(captcha1, captcha2, x, y):
                        return x  # 找到缺口的左侧边界 在x方向上的位置
    
        def get_move_track(self, gap):
            track = []  # 移动轨迹
            current = 0  # 当前位移
            # 减速阈值
            mid = gap * 4 / 5  # 前4/5段加速 后1/5段减速
            t = 0.2  # 计算间隔
            v = 0  # 初速度
            while current < gap:
                if current < mid:
                    a = 3  # 加速度为+3
                else:
                    a = -3  # 加速度为-3
                v0 = v  # 初速度v0
                v = v0 + a * t  # 当前速度
                move = v0 * t + 1 / 2 * a * t * t  # 移动距离
                current += move  # 当前位移
                track.append(round(move))  # 加入轨迹
            return track
    
        def move_slider(self, track):
            slider = self.wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, '.geetest_slider_button')))
            ActionChains(self.driver).click_and_hold(slider).perform()
            for x in track:  # 只有水平方向有运动 按轨迹移动
                ActionChains(self.driver).move_by_offset(xoffset=x, yoffset=0).perform()
            sleep(1)
            ActionChains(self.driver).release().perform()  # 松开鼠标
    
        def main(self):
            self.input_name_password()
            self.click_login_button()
            self.get_geetest_image()
            gap = self.get_diff_location()  # 缺口左起点位置
            gap = gap - 6  # 减去滑块左侧距离图片左侧在x方向上的距离 即为滑块实际要移动的距离
            track = self.get_move_track(gap)
            print("移动轨迹", track)
            self.move_slider(track)
    
    
    if __name__ == "__main__":
        springAutumn = SliderVerificationCode()
        springAutumn.main()
             
    

     

    展开全文
  • 接下来,我们介绍一下滑动验证码吧! 它是怎么样的呢?像手机解锁一样?爆照!如下为网易云易盾的行为式验证码中的滑动验证码。 仔细看上面的提示,就能明白如何操作。(强迫症的人看见图就条件反射的想要去拖动...
  • 摘要:我们在做一些后台系统的登录验证的时候。难免会用到验证码功能,来辅助进行验证,提高安全性,在我们日常生活中,验证方式无处不在,最多的是... 两个文本框+一个获取验证码按钮,文本框用来输入手机号和获...
  • 具体详情见代码,研究网站,随便输入手机号点击获取验证码 在自己写代码前参考了一批博客,是把所有验证码...直接给缺口图片,先滑动到缺口找到完整验证码图片,对比有缺口的验证码图片,然后计算缺口坐标,再利用seleniu
  • 用selenium模拟浏览器登录淘宝,使用账号密码的方式登录淘宝,但是在登录的时候遇到需要滑动验证,使用selenium模拟点击滑块,滑动验证码完成登录。 本文的代码现测可用。做个记录,方便以后查看。 链接:...
  • PC手机端和嵌入式滑动拼图验证码三种效果
  • 主要介绍了JS实现PC手机端和嵌入式滑动拼图验证码三种效果,非常不错,具有参考借鉴价值,需要的朋友可以参考下
  • 电脑和手机移动端都适用的jQuery拖动滑块图片拼图验证码插件,通过鼠标拖动或触屏滑动填充拼图来进行安全验证,点击刷新可以更换当前待验证的图片。HTML & css:拖动滑块图片拼图验证码插件.slidercaptcha {...
  •  我们可以通过修改Django认证系统的认证后端(主要是authenticate方法)来支持登录账号既可以是用户名也可以是手机号。 修改Django认证系统的认证后端需要继承django.contrib.auth.backends...
  • 本文详细介绍了破解极验滑动验证码的所有过程,包括破解思路,实现步骤以及测试结果,相信你看完之后也能轻松破解滑动验证码;#短信防洪轰炸# 一丶解析验证码组成 从上面三张图来看,极验滑动拼图验证码是由一个小...
  • 本文详细介绍了针对发送短信验证码接口的安全性测试过程,包含思路、部分测试代码已经测试结果。 本次测试网站 --小米(mi.com) 小米是一家以手机、智能硬件和IoT平台为核心的互联网公司,以智能手机、智能电视、...
  • 之前动手用python写了一个qq空间自动点赞的脚本,登录方法采用的是selenium获取网页截图然后返回二维码截图,用手机qq扫一扫进行登录. 然后又用flask简单的写成了网页,放到了自己的服务器上,这样每次只需要输入网址就...
  • 手机应用程序验证代码滑动测试。 该项目通过图片识别的方式,解决手机app登录认证中出现的滑动弹框的自动识别和滑动。从而实现自动登录。 有兴趣可以共同优化改进。 版本1.0 1,实现从截图中识别到验证框的开始和...
  • 滑块验证码,拖拽效果,拖拽滑动验证码,从左边拖拽到右边实现验证。 仅支持移动手机
  • 验证码

    2018-09-04 23:41:16
    就我所学而言,验证码可以分为两大类,一类是手机验证码,另一类是网页验证码,网页验证码又可以分为字符串验证码和滑动验证码,以下分别进行说明。 1.手机验证码.手机验证码一般需要借助第三方的云端,就我了解,...
  • 滑块验证码 同时支持PC电脑端和手机移动端。滑块验证码,拖拽效果,拖拽滑动验证码,从左边拖拽到右边实现验证。
  • js如何模拟手机滑动,点击

    千次阅读 2019-05-16 09:54:52
    此插件能干什么?github源码 一句话概括:通过程序主动触发移动端滑动、拖拽、触碰...注意,请在手机模式查看所有演示地址,插件仅支持移动端 拿常见的滑动相关demo举例,程序触发动端滑动 jQuery-slide滑块验证码 ...
  • 现今验证方式多种多样,例如短信验证码、图形验证码、语音验证码、滑动验证码、口令验证码等。我们在注册账号、登陆网站的时候,会发现在获取关键的短信验证码时会遇到先输入图形验证码来增加操作的复杂性,表面上看...

空空如也

空空如也

1 2 3 4 5 6
收藏数 110
精华内容 44
关键字:

手机滑动验证码