自动识别图形验证码
Posted zhangjianying
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了自动识别图形验证码相关的知识,希望对你有一定的参考价值。
现在大多数网站都采用了验证码来防止暴力破解或恶意提交。但验证码真的就很安全吗?真的就不能被机器识别??
我先讲讲我是怎么实现站外提交留言到一个网站的程序。
这个网站的留言版大致如下:
我一看这种简单的4位数字验证码,马上就感觉到有戏了。直觉告诉我让电脑来识别这些图片验证码据对简单o(∩_∩)o...
首先我马上在这个页面用右键菜单看源代码
知道验证码获取页面后 你可以直接用 http://www.XXXX.com/imgchk/validatecode.asp 这样去访问你会发现你打开的就是一个验证码图片。
对的其实返回的就是图片文件的2进制流而已。接着先用右键保存一张验证码的图片。因为要开始分析这张图片了,什么用什么工具?PhotoShop????不用就一般的画图工具就可以了。我们要搞清楚的是 这几个数字分别占几个像素就可以了。
可以看出 一个数字5*9 也就是45个像素。恩 这就可以了 另外我们可以看出 默认区域就是白色
(姑且说是白色因为我们肉眼看就是白色)
那么我的程序识别原理就是固定去扫描这45个像素点。看每个点的颜色是不是和默认的颜色一致
一致的话就标记为0 ,不一致就标记为1 。
如一个数子是2 那么我的程序扫描出来的图像就应该是:
011110
100001
000001
000001
000010
000100
001000
010000
100000
111111
如果一个数字是7那么扫描出来的图像就是:
111111
100001
000010
000010
000100
000100
001000
001000
010000
010000
恩,就这么简单呵呵。下面给出图像 扫描的java类 (不好意思,在我会的语言里面除开java就剩sql了)
package com.util;
// ~--- JDK imports ------------------------------------------------------------
import com.sun.image.codec.jpeg.JPEGCodec;
import com.sun.image.codec.jpeg.JPEGEncodeParam;
import com.sun.image.codec.jpeg.JPEGImageEncoder;
import java.awt. * ;
import java.awt.image. * ;
import java.io. * ;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.net. * ;
import javax.imageio. * ;
import javax.imageio.ImageIO;
/** */ /**
* 登陆验证图片转换为数字
*
*
* @version 1.0, 08/04/20
* @author 张健滢
*/
public class ImgIdent ... {
// 数字字符比特表
private final long[][] NUMERIC = ...{
...{ 512104545, 562436190 }, // '0'
...{ 148931080, 136348222 }, // '1'
...{ 511971394, 69273663 }, // '2'
...{ 511971406, 17045598 }, // '3'
...{ 35168914, 586948743 }, // '4'
...{ 1065486398, 17045598 }, // '5'
...{ 239208494, 830871646 }, // '6'
...{ 1065623684, 69239824 }, // '7'
...{ 512104542, 562436190 }, // '8'
...{ 512104547, 486805660 }
}; // '9'
// 字框高
private int intCharHeight = 10;
// 字框横向间隙
private int intCharSpaceH = 5;
// 字框纵向间隙
private int intCharSpaceY = 1;
// 字框宽
private int intCharWidth = 5;
private int IntImgHeight;
private BufferedImage img;
private int intBgColor;
private int intCharColor;
private int intImgWith;
private int intMaxX;
private int intMaxY;
private int intMinX;
private int intMinY;
// 座标原点
private Point pOrigin;
private String strNum;
/** *//**
* Constructs ...
*
*
* @param img
*
* @throws IOException
*/
public ImgIdent(BufferedImage img) throws IOException ...{
this.img = img;
init();
}
/** *//**
* 构造函数
* @param file 本地文件
* @throws IOException
*/
public ImgIdent(File file) throws IOException ...{
img = ImageIO.read(file);
init();
}
/** *//**
* 构造函数
* @param url 远程文件
* @throws IOException
*/
public ImgIdent(URL url) throws IOException ...{
img = ImageIO.read(url);
init();
}
/** *//**
* 类初始工作
*/
private void init() ...{
// 得到图象的长度和宽度
intImgWith = img.getWidth();
IntImgHeight = img.getHeight();
// 得到图象的背景颜色
intBgColor = img.getRGB(7, 4);
// System.out.println(intBgColor);
// 初始化图象原点座标
pOrigin = new Point(0, 0);
}
/** *//**
* Method description
*
*/
private void getBaseInfo() ...{
System.out.println(intBgColor + "|" + intCharColor);
System.out.println(intMinX + "|" + intMinY + "|" + intMaxX + "|" + intMaxY);
}
/** *//**
* 得到字符的左上右下点座标
* @param intNo int 第n个字符
* @return int[]
*/
private Point[] getCharRange(int intNo) ...{
// 左上右下点座标
Point pTopLeft = new Point(0, 0);
Point pBottomRight = new Point(0, 0);
// 左上点
pTopLeft.x = pOrigin.x + intCharWidth * (intNo - 1) + intCharSpaceH * (intNo - 1);
pTopLeft.y = pOrigin.y;
// 右下点
pBottomRight.x = 1 + pOrigin.x + intCharWidth * intNo + intCharSpaceH * (intNo - 1) - 1;
pBottomRight.y = pOrigin.y + intCharHeight - 1;
return new Point[] ...{ pTopLeft, pBottomRight };
}
/** *//**
* 与背景颜色比较返回相应的字符
* @param x int 横座标
* @param y int 纵座标
* @return char 返回字符
*/
private char getBit(int x, int y) ...{
int intCurtColor;
intCurtColor = img.getRGB(x, y);
// System.out.println("[" + x + "," + y + "]" + intCurtColor + "==" + intBgColor + "==>" + (Math.abs(intCurtColor) >7308252));
// return (Math.abs(intCurtColor) >= 5689325)
// ? '0'
// : '1';
return (intCurtColor == intBgColor)
? '0'
: '1';
// 5689325 6008535
}
验证码识别——图形验证码
我先讲讲我是怎么实现站外提交留言到一个网站的程序。
这个网站的留言版大致如下:
我一看这种简单的4位数字验证码,马上就感觉到有戏了。直觉告诉我让电脑来识别这些图片验证码据对简单o(∩_∩)o...
首先我马上在这个页面用右键菜单看源代码
知道验证码获取页面后 你可以直接用 http://www.XXXX.com/imgchk/validatecode.asp 这样去访问你会发现你打开的就是一个验证码图片。
对的其实返回的就是图片文件的2进制流而已。接着先用右键保存一张验证码的图片。因为要开始分析这张图片了,什么用什么工具?PhotoShop????不用就一般的画图工具就可以了。我们要搞清楚的是 这几个数字分别占几个像素就可以了。
可以看出 一个数字5*9 也就是45个像素。恩 这就可以了 另外我们可以看出 默认区域就是白色
(姑且说是白色因为我们肉眼看就是白色)
那么我的程序识别原理就是固定去扫描这45个像素点。看每个点的颜色是不是和默认的颜色一致
一致的话就标记为0 ,不一致就标记为1 。
如一个数子是2 那么我的程序扫描出来的图像就应该是:
011110
100001
000001
000001
000010
000100
001000
010000
100000
111111
如果一个数字是7那么扫描出来的图像就是:
111111
100001
000010
000010
000100
000100
001000
001000
010000
010000
恩,就这么简单呵呵。下面给出图像 扫描的java类 (不好意思,在我会的语言里面除开java就剩sql了)
package com.util;
// ~--- JDK imports ------------------------------------------------------------
import com.sun.image.codec.jpeg.JPEGCodec;
import com.sun.image.codec.jpeg.JPEGEncodeParam;
import com.sun.image.codec.jpeg.JPEGImageEncoder;
import java.awt. * ;
import java.awt.image. * ;
import java.io. * ;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.net. * ;
import javax.imageio. * ;
import javax.imageio.ImageIO;
/** */ /**
* 登陆验证图片转换为数字
*
*
* @version 1.0, 08/04/20
* @author 张健滢
*/
public class ImgIdent ... {
// 数字字符比特表
private final long[][] NUMERIC = ...{
...{ 512104545, 562436190 }, // '0'
...{ 148931080, 136348222 }, // '1'
...{ 511971394, 69273663 }, // '2'
...{ 511971406, 17045598 }, // '3'
...{ 35168914, 586948743 }, // '4'
...{ 1065486398, 17045598 }, // '5'
...{ 239208494, 830871646 }, // '6'
...{ 1065623684, 69239824 }, // '7'
...{ 512104542, 562436190 }, // '8'
...{ 512104547, 486805660 }
}; // '9'
// 字框高
private int intCharHeight = 10;
// 字框横向间隙
private int intCharSpaceH = 5;
// 字框纵向间隙
private int intCharSpaceY = 1;
// 字框宽
private int intCharWidth = 5;
private int IntImgHeight;
private BufferedImage img;
private int intBgColor;
private int intCharColor;
private int intImgWith;
private int intMaxX;
private int intMaxY;
private int intMinX;
private int intMinY;
// 座标原点
private Point pOrigin;
private String strNum;
/** *//**
* Constructs ...
*
*
* @param img
*
* @throws IOException
*/
public ImgIdent(BufferedImage img) throws IOException ...{
this.img = img;
init();
}
/** *//**
* 构造函数
* @param file 本地文件
* @throws IOException
*/
public ImgIdent(File file) throws IOException ...{
img = ImageIO.read(file);
init();
}
/** *//**
* 构造函数
* @param url 远程文件
* @throws IOException
*/
public ImgIdent(URL url) throws IOException ...{
img = ImageIO.read(url);
init();
}
/** *//**
* 类初始工作
*/
private void init() ...{
// 得到图象的长度和宽度
intImgWith = img.getWidth();
IntImgHeight = img.getHeight();
// 得到图象的背景颜色
intBgColor = img.getRGB(7, 4);
// System.out.println(intBgColor);
// 初始化图象原点座标
pOrigin = new Point(0, 0);
}
/** *//**
* Method description
*
*/
private void getBaseInfo() ...{
System.out.println(intBgColor + "|" + intCharColor);
System.out.println(intMinX + "|" + intMinY + "|" + intMaxX + "|" + intMaxY);
}
/** *//**
* 得到字符的左上右下点座标
* @param intNo int 第n个字符
* @return int[]
*/
private Point[] getCharRange(int intNo) ...{
// 左上右下点座标
Point pTopLeft = new Point(0, 0);
Point pBottomRight = new Point(0, 0);
// 左上点
pTopLeft.x = pOrigin.x + intCharWidth * (intNo - 1) + intCharSpaceH * (intNo - 1);
pTopLeft.y = pOrigin.y;
// 右下点
pBottomRight.x = 1 + pOrigin.x + intCharWidth * intNo + intCharSpaceH * (intNo - 1) - 1;
pBottomRight.y = pOrigin.y + intCharHeight - 1;
return new Point[] ...{ pTopLeft, pBottomRight };
}
/** *//**
* 与背景颜色比较返回相应的字符
* @param x int 横座标
* @param y int 纵座标
* @return char 返回字符
*/
private char getBit(int x, int y) ...{
int intCurtColor;
intCurtColor = img.getRGB(x, y);
// System.out.println("[" + x + "," + y + "]" + intCurtColor + "==" + intBgColor + "==>" + (Math.abs(intCurtColor) >7308252));
// return (Math.abs(intCurtColor) >= 5689325)
// ? '0'
// : '1';
return (intCurtColor == intBgColor)
? '0'
: '1';
// 5689325 6008535
}
验证码识别——图形验证码