现在大多数网站都采用了验证码来防止暴力破解或恶意提交。但验证码真的就很安全吗?真的就不能被机器识别??
我先讲讲我是怎么实现站外提交留言到一个网站的程序。
这个网站的留言版大致如下:

我一看这种简单的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;

public class ImgIdent {

// 数字字符比特表

private final long[][] NUMERIC = {

},    // '0'

},    // '1'

},     // '2'

},     // '3'

},     // '4'

},    // '5'

},    // '6'

},    // '7'

},    // '8'

}

};                               // '9'

// 字框高
;

// 字框横向间隙
;

// 字框纵向间隙
;

// 字框宽
;

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;

public ImgIdent(BufferedImage img) throws IOException {

this.img = img;

init();

}

public ImgIdent(File file) throws IOException {

img = ImageIO.read(file);

init();

}

public ImgIdent(URL url) throws IOException {

img = ImageIO.read(url);

init();

}

private void init() {

// 得到图象的长度和宽度
        intImgWith   = img.getWidth();

IntImgHeight = img.getHeight();

// 得到图象的背景颜色
);

// System.out.println(intBgColor);

// 初始化图象原点座标
);

}

private void getBaseInfo() {

System.out.println(intBgColor + "|" + intCharColor);

System.out.println(intMinX + "|" + intMinY + "|" + intMaxX + "|" + intMaxY);

}

private Point[] getCharRange(int intNo) {

// 左上右下点座标
);

Point pBottomRight );

// 左上点
);

pTopLeft.y = pOrigin.y;

// 右下点
;

pBottomRight.y ;

return new Point[] { pTopLeft, pBottomRight };

}

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)

'

: ';

// 5689325    6008535
    }

private String getCharString(int intNo) {

// 本字符的左上右下点座标
        Point[] p            = getCharRange(intNo);

Point   pTopLeft     ];

Point   pBottomRight ];

// 换算边界值
        int intX1, intY1, intX2, intY2;

intX1 = pTopLeft.x;

intY1 = pTopLeft.y;

intX2 = pBottomRight.x;

intY2 = pBottomRight.y;

//      System.out.println("intX1=" + intX1);
//      System.out.println("intY1=" + intY1);
//      System.out.println("intX2=" + intX2);
//      System.out.println("intY2=" + intY2);

// 在边界内循环取象素
        int    i, j;

String strChar = "";

for (i = intY1; i <= intY2; i++) {

for (j = intX1; j <= intX2; j++) {

System.out.print(getBit(j, i));

strChar = strChar + getBit(j, i);

}

System.out.println();

}

System.out.println();

return strChar;

}

public int getNum(int intNo) {

// 取得位字符串
        String strChar = getCharString(intNo);

// System.out.println(intNo+"=="+strChar);

// 取得串高位串和低位串
);

String strCharLow  );

// 计算高位和低位值
);

System.out.println(lCharHigh);

);

System.out.println(lCharLow);

// 在数字中循环比较
        int intNum = '*';

; i++) {

])) {

intNum = i;

break;

} else {

)) {

intNum ;

}    // 834533329 242870177

else {

intNum ;

}    // 默认为1   低位为    937393609  937393601
            }

}

return intNum;

}

public String getValidatecode(int length) {

String strNum = "";

; i <= length; i++) {

synchronized (this) {

strNum += String.valueOf(getNum(i));

}

}

return strNum;

}

public void saveJPEG(BufferedImage iag, String savePath) throws FileNotFoundException, IOException {

OutputStream     jos     = new FileOutputStream(savePath);

JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(jos);

JPEGEncodeParam  jpegEP  = JPEGCodec.getDefaultJPEGEncodeParam(iag);

jpegEP.setQuality((, true);

encoder.encode(iag, jpegEP);

jos.flush();

jos.close();

}

}

恩这样数字是可以识别出来了,可以我要怎么完成提交那块的工作呢?好在Apache已经为我做完了。我用了
HttpClient这样一个模拟Http协议的小工具包。我只要往那个 Add_MSG.asp里面提交就完了。

package com.util;

//~--- non-JDK imports --------------------------------------------------------

import org.apache.commons.httpclient.*;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.params.HttpClientParams;
import org.apache.commons.httpclient.params.HttpMethodParams;

//~--- JDK imports ------------------------------------------------------------

import java.awt.image.BufferedImage;

import java.io.InputStream;

import javax.imageio.ImageIO;

public class MyHttpClient {

public synchronized void doSomeThing(String title, String name, String Content, String proIP, int port,

boolean usePro) {

// 构造HttpClient的实例
        HttpClient       httpClient   = new HttpClient();

HttpClientParams clientParams = new HttpClientParams();

// 隐藏自己请求相关的信息
        clientParams.setParameter("http.useragent", "Mozilla/4.0 (compatible; FIREFOX 9.0; IBM AIX 5)");

// httpClient.getHttpConnectionManager().getParams().setSoTimeout(30 * 1000);
        clientParams.setHttpElementCharset("GBK");

HttpState httpState = new HttpState();

httpClient.setParams(clientParams);

httpClient.getParams().setParameter(HttpClientParams.HTTP_CONTENT_CHARSET, "GBK");

httpClient.setState(httpState);

clientParams.setVersion(HttpVersion.HTTP_1_1);

// httpClient.getHostConfiguration().setProxy("148.233.159.58", 3128);

if (usePro)    // 使用代理

{

httpClient.getHostConfiguration().setProxy(proIP, port);

}

// 创建GET方法的实例
        GetMethod getMethod = new GetMethod("http://www.XXXcom/Guestbook/imgchk/validatecode.asp");

// 使用系统提供的默认的恢复策略
        getMethod.getParams().setParameter(HttpMethodParams.RETRY_HANDLER, new DefaultHttpMethodRetryHandler());

try {

// 执行getMethod
            int statusCode = httpClient.executeMethod(getMethod);

// System.out.println(statusCode);

if (statusCode != HttpStatus.SC_OK) {

System.err.println("Method failed: " + getMethod.getStatusLine());

}    // 读取内容

InputStream inStream = getMethod.getResponseBodyAsStream();

// 处理内容

// System.out.println(new String(responseBody));
            BufferedImage iag      = ImageIO.read(inStream);

ImgIdent      imgIdent = new ImgIdent(iag);

// imgIdent.saveJPEG(iag, "C:/ddd.jpg");
);

System.out.println(validate);

PostMethod method  = new PostMethod("http://www.XXX.com/Guestbook/add_msg.asp");

String     connect = Content;

String     Title   = title;

method.setParameter("subject", Title);

method.setParameter("g_name", name);

method.setParameter("companyname", "");

method.setParameter("mail", "");

method.setParameter("homepageurl", "http://");

method.setParameter("pic", "p5.gif");

method.setParameter("validatecode", validate);

method.setParameter("content", connect);

//          if (todo) {
            int code = httpClient.executeMethod(method);

// String Stringresponse = new String(method.getResponseBodyAsString().getBytes("8859_1"));

// 打印返回的信息

// System.out.println(Stringresponse);
//          }

method.releaseConnection();

//          System.out.println(iag.getHeight());
//          System.out.println(iag.getWidth());
//          //背景 颜色
//          intBgColor = iag.getRGB(38, 0);
//          System.out.println("intBgColor=" + intBgColor);
//
//
//          intBgColor = iag.getRGB(0, 0);
//          System.out.println("intBgColor=" + intBgColor);

} catch (Exception e) {

// 发生网络异常
            e.printStackTrace();

} finally {}

// 释放连接   getMethod.releaseConnection();  }
        getMethod.releaseConnection();

}

}

恩 就这样了,最后结合SAF整成这样了。什么?为什么不用SWT?想过了SWING才是王道o(∩_∩)o...

[Java] 识别图片验证码的更多相关文章

  1. 【java+selenium3】Tesseract-OCR识别图片验证码 (十六)

    [java+selenium+Tesseract-OCR(图片识别)+AutoIt(windows窗口识别)]完成自动化图片验证码识别! 一.AutoIt(windows窗口识别)参考:https:/ ...

  2. python 识别图片验证码报IOError

    说一下困扰了我一周的问题:识别图片验证码 本来我按照安装步骤(http://www.cnblogs.com/yeayee/p/4955506.html?utm_source=tuicool&u ...

  3. 用Java实现图片验证码功能

    一.什么是图片验证码? 可以参考下面这张图: 我们在一些网站注册的时候,经常需要填写以上图片的信息. 1.图片生成实体类: package com.hexianwei.graphic; import ...

  4. python爬虫20 | 小帅b教你如何使用python识别图片验证码

    当你在爬取某些网站的时候 对于你的一些频繁请求 对方会阻碍你 常见的方式就是使用验证码 验证码的主要功能 就是区分你是人还是鬼(机器人) 人 想法设法的搞一些手段来对付技术 而 技术又能对付人们的想法 ...

  5. java实现图片验证码

    一.验证码生成类 package hbi.tech.utils; import javax.imageio.ImageIO; import java.awt.*; import java.awt.im ...

  6. 使用burp插件captcha-killer识别图片验证码

    0x01 开发背景 说起对存在验证码的登录表单进行爆破,大部分人都会想到PKav HTTP Fuzzer,这款工具在前些年确实给我们带来了不少便利.反观burp一直没有一个高度自定义通杀大部分图片验证 ...

  7. Java 生产图片验证码

    import java.awt.Color;import java.awt.Font;import java.awt.Graphics;import java.awt.Graphics2D;impor ...

  8. 识别图片验证码的三种方式(scrapy模拟登陆豆瓣网)

    1.通过肉眼识别,然后输入到input里面 from PIL import image Image request.urlretrieve(url,'image')  #下载验证码图片 image = ...

  9. 【转】Python OCR识别图片验证码

    转载自:博客 对于某些网站登录的时候,往往需要输入验证码才能实现登录.如果要爬虫这类网站,往往总会比这个验证码导致无法爬取数据.以下介绍一种比较折中的方法,也是比较可行的方法: 实现思想: 1.通过截 ...

随机推荐

  1. leetcode:Roman to Integer(罗马数字转化为罗马数字)

    Question: Given a roman numeral, convert it to an integer. Input is guaranteed to be within the rang ...

  2. svn import 向Google code里导入初始代码

    其实很简单的问题,花费了这么多时间,想把初始代码导入到Google code里,用VisaulSVN插件的Switch功能也不可以,Google code上虽然有上传,但是只能单个文件传...... ...

  3. (转载)OC学习篇之---类的延展

    前一篇文章我们介绍了类的类目概念和使用,那么这篇文章我们继续来介绍一下OC中的一个特性:延展. 其实说白了,延展就是弥补C语言中的前向申明,我们知道,在C语言中,如果你想调用一个函数的话,那么在此之前 ...

  4. kali ssh 登录

    kali 开启ssh 登录:可在windows 中通过 xshell 登录,方便操作. 修改sshd_config文件, vi /etc/ssh/sshd_config 将#PasswordAuthe ...

  5. Python学习第二天数组

    1:Python定义数组:a=[0,1,2,3,4] ;   打印数组list(a); 这时:a[0]=0, a[1]=1, a[[2]=2...... 1.1:如果想定义一个很长的数组可以用到pyt ...

  6. Systemd Unit文件中PrivateTmp字段详解-Jason.Zhi

    如下图,在开发调试的时候会遇到这么一个问题. file_put_contents时,$tmp_file显示的目标文件是/tmp/xxx.而这个文件实际放在linux的目录却是/tmp/systemd- ...

  7. 桶排序-Node.js

    , , , , ]; var a = [], i; ; i < b.length; i++) { var num = b[i]; a[num] = a[num]||; a[num] ++; nu ...

  8. 调试Python代码的工具

    pdb: 首先来说Python里内建的调试器,pdb.它利用一个简单的命令行界面,还有很多你在用调试器时用得上的功能.帮助系统能为你指出你能运行的命令,比如单步调试代码,操纵调用栈和设置断点. 一些它 ...

  9. php 的简单易用的调式方法,打印方法

    简单的调试方法:echo, print_r, var_dump, exit, debug_backtrace(), debug_print_backtrace(), gettype(), get_cl ...

  10. 第三百二十一天 how can I 坚持

    上班第一天,感觉时间过得好慢. 心里好烦,做什么都没心情,感觉没有勇气了,虽然早上说了那么多,但不敢去面对了. 咋整? <猪老三><野子>. 好想去看<美人鱼> 不 ...