验证码识别<1>
1. 引子
前两天访问学校自助服务器()缴纳网费,登录时发现这系统的验证码也太过“清晰”了,突然脑袋里就蹦出一个想法:如果能够自动识别验证码,然后采用暴力破解的方式,那么密码不是可以轻易被破解吗?
ps:用户名就是学号,可以轻易获得,而密码是系统随机生成的6位数,组合方式仅有 10^6种,假设每次尝试须要50ms,那么大概需要14个小时,如果采用多线程,多个虚拟机(java)同时工作,估计把所有密码过一遍不会超过1个小时,这效率还凑合吧。。。

2. 分析
问题的关键就在于验证码识别,至于如何请求服务器,用java分分钟搞定。学习了一些网友写的关于验证码识别的blog,如:http://blog.csdn.net/problc/article/details/5794460。发现它的基本步骤就是:【去噪】、【分割】、【匹配】,【识别】。
① 去噪
即去除背景和干扰线,并且将背景置为白色,文字置为黑色,便于后面匹配。验证码获取地址:http://202.118.166.244:8080/selfservice/common/web/verifycode.jsp。通过观察会发现,文字部分颜色较深(r,g,b基本小于110),干扰部分颜色较浅。于是可以这样【去噪】:
public static BufferedImage denoising(BufferedImage image) {
for (int x = 0; x < image.getWidth(); x++) {
for (int y = 0; y < image.getHeight(); y++) {
Color color = new Color(image.getRGB(x, y));
int red = color.getRed();
int green = color.getGreen();
int blue = color.getBlue();
if (red > 105 && green > 105 && blue > 105) {
image.setRGB(x, y, Color.WHITE.getRGB());
} else {
image.setRGB(x, y, Color.BLACK.getRGB());
}
}
}
return image;
}
看看效果:
处理前:
处理后:
,效果还是不错的!
② 分割
分割很简单,将验证码按文字等分。
/**
* 分割图片
*
* @param img
* @param splitNum
* @return
* @throws IOException
*/
public static List<BufferedImage> splitImage(BufferedImage img, int splitNum) throws IOException {
int width = img.getWidth();
int height = img.getHeight();
int splitWidth = width / splitNum;
List<BufferedImage> bufferedImages = new ArrayList<BufferedImage>();
for (int i = 0; i < splitNum; i++) {
bufferedImages.add(img.getSubimage(i * splitWidth, 0, splitWidth, height));
}
return bufferedImages;
}
③ 匹配
在匹配之前,要利用前面的两个方法得到所有字符的片段,用于匹配。像这样:

然后设计匹配算法,这一步比较关键,匹配算法的好坏将直接导致识别的正确与否。因为观察到文字都没有进行旋转,因此这里采用:用一个集合记录下图片每一纵行所拥有的黑色像素点的个数(没有像素的纵行不记录),将这个集合作为对应图片的指纹。然后分割好的验证码片段与上面的标准片段进行一一比对,最后组合在一起,从而可以识别出验证码。
/**
* 单个字符进行匹配
*
* @param img
* @param regularDataList
* @return
*/
public String matchSingleWord(BufferedImage img, List<List<Integer>> regularDataList) {
String result = null;
int maxRank = 0;
List<Integer> matchedData = getFingerprint(img);
for (int i = 0; i < regularDataList.size(); i++) {
int rank = 0;
List<Integer> regularData = regularDataList.get(i);
int minColumn = Math.min(regularData.size(), matchedData.size());
for (int j = 0; j < minColumn; j++) {
if (matchedData.get(j) == regularData.get(j)) {
rank++;
}
}
if (rank > maxRank) {
maxRank = rank;
result = i + "";
}
}
return result;
}
/**
* 获取图像"指纹"
*
* @param image
* @return
*/
private static List<Integer> getFingerprint(BufferedImage image) {
List<Integer> list = new ArrayList<Integer>();
for (int x = 0; x < image.getWidth(); x++) {
int count = 0;
for (int y = 0; y < image.getHeight(); y++) {
// System.out.println(image.getRGB(x, y));
if (image.getRGB(x, y) == 0xFF000000) {
count++;
}
}
if (count != 0) {
list.add(count);
}
}
return list;
}
/**
* 加载作为标准的指纹List
*
* @return
* @throws IOException
*/
private static List<List<Integer>> loadMatchDataList() throws IOException {
List<List<Integer>> matchData = new ArrayList<List<Integer>>();
File dir = new File("C:\\Users\\Administrator\\Desktop\\verifycode\\match");
File[] files = dir.listFiles();
for (File file : files) {
matchData.add(getFingerprint(ImageIO.read(file)));
}
return matchData;
}
④ 识别
将以上识别出的单个字符组合在一起,就得到验证码啦。
public static void main(String[] args) throws Exception {
BufferedImage image = ImageIO.read(new URL("http://202.118.166.244:8080/selfservice/common/web/verifycode.jsp"));
ImageIO.write(image, "png", new File("C:\\Users\\Administrator\\Desktop\\verifycode\\verifycode_src.png"));
image = denoising(image);
// 注意:最好以png格式输出,否则可能导致图片失真
ImageIO.write(image, "png", new File("C:\\Users\\Administrator\\Desktop\\verifycode\\verifycode.png"));
List<BufferedImage> images = splitImage(image, 4);
List<List<Integer>> regularFingerprintList = loadMatchDataList();
String result = "";
for (BufferedImage bufferedImage : images) {
result += matchSingleWord(bufferedImage, regularFingerprintList);
}
System.out.println("验证码是:" + result);
}
结果:
,
,完全正确。
3. 总结
总的来说,由于该类型验证码本生较为简单,所以处理起来十分顺利。但不管验证码怎么变化,基于这种识别算法的基本就是以上几部,具体做法根据具体案例实现。
最后随便搞一个账号来测试,用时2个多小时跑出了密码。。。
先写到这里,以后再研究其他识别算法。
验证码识别<1>的更多相关文章
- 字符型图片验证码识别完整过程及Python实现
字符型图片验证码识别完整过程及Python实现 1 摘要 验证码是目前互联网上非常常见也是非常重要的一个事物,充当着很多系统的 防火墙 功能,但是随时OCR技术的发展,验证码暴露出来的安全问题也越 ...
- 简单的验证码识别(opecv)
opencv版本: 3.0.0 处理验证码: 纯数字验证码 (颜色不同,有噪音,和带有较多的划痕) 测试时间 : 一天+一晚 效果: 比较挫,可能是由于测试的图片是在太小了的缘故. 原理: 验证码 ...
- 利用开源程序(ImageMagick+tesseract-ocr)实现图像验证码识别
--------------------------------------------------低调的分割线-------------------------------------------- ...
- 基于LeNet网络的中文验证码识别
基于LeNet网络的中文验证码识别 由于公司需要进行了中文验证码的图片识别开发,最近一段时间刚忙完上线,好不容易闲下来就继上篇<基于Windows10 x64+visual Studio2013 ...
- Java验证码识别解决方案
建库,去重,切割,识别. package edu.fzu.ir.test; import java.awt.Color; import java.awt.image.BufferedImage; im ...
- 简单验证码识别(matlab)
简单验证码识别(matlab) 验证码识别, matlab 昨天晚上一个朋友给我发了一些验证码的图片,希望能有一个自动识别的程序. 1474529971027.jpg 我看了看这些样本,发现都是很规则 ...
- Python验证码识别处理实例(转载)
版权声明:本文为博主林炳文Evankaka原创文章,转载请注明出处http://blog.csdn.net/evankaka 一.准备工作与代码实例 1.PIL.pytesser.tesseract ...
- 验证码识别--type2
验证码识别--type2 终于来到了彩色图像,一定有一些特点 这里的干扰项是色彩不是很鲜艳的.灰色的线条,还有单独的干扰点,根据这些特性进行去除 直接ostu的话,有的效果好,有的效果不好 本来是 ...
- 验证码识别--type5
验证码识别--type5 每一种验证码都是由人设计出来.在设计过程中,可能由于多个方面的原因,造成了这样或那样的可以被利用的漏洞.验证码识别,首先需要解决的问题就是发现这些漏洞--然后利用漏洞解决问题 ...
随机推荐
- Jquery 搭配 css 使用,简单有效
前几篇博客中讲了Jquery的基础和点击实际,下面来说一下和css搭配着来怎么做 还是和往常一样,举个例子 好几个方块,然后设置颜色 <!DOCTYPE html PUBLIC "-/ ...
- web前端基础知识
#HTML 什么是HTML,和他ML... 网页可以比作一个装修好了的,可以娶媳妇的房子. 房子分为:毛坯房,精装修 毛坯房的修建: 砖,瓦,水泥,石头,石子.... 精 ...
- 07. Web大前端时代之:HTML5+CSS3入门系列~H5 地理位置
Web大前端时代之:HTML5+CSS3入门系列:http://www.cnblogs.com/dunitian/p/5121725.html 源码:https://github.com/duniti ...
- SQL必备知识点
经典SQL语句大全 基础 1.说明:创建数据库.说明:删除数据库drop database dbname3.说明:备份sql server--- 创建 备份数据的 device.说明:创建新表crea ...
- Webpack 配置摘要
open-browser-webpack-plugin 自动打开浏览器 html-webpack-plugin 通过 JS 生成 HTML webpack.optimize.UglifyJsPlugi ...
- .Net Core MVC 网站开发(Ninesky) 2.2、栏目管理功能-System区域添加
在asp或asp.net中为了方便网站的结构清晰,通常把具有类似功能的页面放到一个文件夹中,用户管理功能都放在Admin文件夹下,用户功能都放在Member文件夹下,在MVC中,通常使用区域(Area ...
- MVC Core 网站开发(Ninesky) 1、创建项目
又要开一个新项目了!说来惭愧,以前的东西每次都没写完,不是不想写完,主要是我每次看到新技术出来我都想尝试一下,看到.Net Core 手又痒了,开始学MVC Core. MVC Core最吸引我的有三 ...
- 谈谈一些有趣的CSS题目(五)-- 单行居中,两行居左,超过两行省略
开本系列,讨论一些有趣的 CSS 题目,抛开实用性而言,一些题目为了拓宽一下解决问题的思路,此外,涉及一些容易忽视的 CSS 细节. 解题不考虑兼容性,题目天马行空,想到什么说什么,如果解题中有你感觉 ...
- 挑子学习笔记:特征选择——基于假设检验的Filter方法
转载请标明出处: http://www.cnblogs.com/tiaozistudy/p/hypothesis_testing_based_feature_selection.html Filter ...
- Java FtpClient 实现文件上传服务
一.Ubuntu 安装 Vsftpd 服务 1.安装 sudo apt-get install vsftpd 2.添加用户(uftp) sudo useradd -d /home/uftp -s /b ...