为了防止一些非法程序通过自动提交数据来刺探用户账号和密码,验证码的利用显得非常必要!验证码的实现是通过后台程序生成图片文件储存在内存中并显示在前台。因此后台生成的图片格式不尽相同!这里以常用的Bmp格式为例!程序的设计思路应该相似,而且在网上也很多相关的程序,但是讲解具体如何实现的却不多!本人也为新手,见谅!
要谈验证码的实现就必须谈谈图片文件的格式了!这里Bmp图片文件的格式包括四个部分:位图文件头;位图信息头;彩色表;定义位图的字节阵列。
位图文件头组成部分如下:
标识:2bites,windows系统都为BM;
用字节表示文件大小:1Dword,整个文件的大小;
保留字:1Dword,必须设置为0;
从文件开始到位图数据开始之间的偏移量:1Dword;
位图信息头长度:1Dword;
位图宽度:1Dword,单位为像素;
位图高度:1Dword,单位为像素;
位图的位面数:1word,其值为1;
位图信息头组成如下:
每个像素的位数:1word,1—单色,4—16位色,8—256位色,16—高彩色位图,24—真彩色,32—真强型真彩色
压缩说明:1dword,0—不压缩,1—RLE 8压缩,2—RLE 4压缩,3—位域存放方式:
用字节表示的位图数据大小:1Dword,必须为4的倍数;
水平分辨率:1Dword,单位为像素/米;
垂直分辨率:1Dword,单位为像素/米;
位图使用的颜色:1Dword;
重要样色数:1Dword,设为0时则都为重要;
说明:以上内容参考《BMP文件格式分析》
我们在看看asp中文件头的写法:
输出图像文件头 :(28bytes)
Response.BinaryWrite ChrB(66) & ChrB(77) & ChrB(230) & ChrB(4) & ChrB(0) & ChrB(0) & ChrB(0) & ChrB(0) &_
ChrB(0) & ChrB(0) & ChrB(54) & ChrB(0) & ChrB(0) & ChrB(0) & ChrB(40) & ChrB(0) &_
ChrB(0) & ChrB(0) & ChrB(40) & ChrB(0) & ChrB(0) & ChrB(0) & ChrB(10) & ChrB(0) &_
ChrB(0) & ChrB(0) & ChrB(1) & ChrB(0)
输出图像文件头分析:
文件标识(2bytes):ChrB(66) & ChrB(77) 说明:ChrB(66):B,ChrB(77):M
文件大小(1dword):ChrB(230) & ChrB(4) & ChrB(0) & ChrB(0)
保留字(1dword):ChrB(0) & ChrB(0) & ChrB(0) & ChrB(0)
偏移量(1dword):ChrB(54) & ChrB(0) & ChrB(0) & ChrB(0)
位图信息头长度(1dword):ChrB(40) & ChrB(0) & ChrB(0) & ChrB(0)
位图的宽度(1word):ChrB(40) & ChrB(0) & ChrB(0) & ChrB(0)
位图的高度(1dword):ChrB(10) & ChrB(0) & ChrB(0) & ChrB(0)
位图的位面数(1word):ChrB(1) & ChrB(0)
输出图像信息头 :(26bytes)
Response.BinaryWrite ChrB(24) & ChrB(0) & ChrB(0) & ChrB(0) & ChrB(0) & ChrB(0) & ChrB(176) & ChrB(4) &_
ChrB(0) & ChrB(0) & ChrB(18) & ChrB(11) & ChrB(0) & ChrB(0) & ChrB(18) & ChrB(11) &_
ChrB(0) & ChrB(0) & ChrB(0) & ChrB(0) & ChrB(0) & ChrB(0) & ChrB(0) & ChrB(0) &_
ChrB(0) & ChrB(0)
输出图像信息头分析:
每个像素的位数(2bytes):ChrB(24) & ChrB(0)
压缩说明(1dword):ChrB(0) & ChrB(0) & ChrB(0) & ChrB(0)
用字节数表示位图数据大小(1dword):ChrB(176) & ChrB(4) & ChrB(0) & ChrB(0)
水平分辨率(1dword):ChrB(18) & ChrB(11) & ChrB(0) & ChrB(0)
垂直分辨率(1dword):ChrB(18) & ChrB(11) & ChrB(0) & ChrB(0)
位图使用的颜色数(1dword):ChrB(0) & ChrB(0) & ChrB(0) & ChrB(0)
重要颜色数(1dword):ChrB(0) & ChrB(0) & ChrB(0) & ChrB(0)
通过上面的分析可以知道输出的该位图为40px*10px,分辨率为71dpi*71dpi,24色,不经过压缩;位图文件头的长度为28bytes,位图信息头的长度为16bytes,所以偏移量为54;整个文件的头文件基本上就是如此!
在看看位图的字节阵列,这里仅仅以数字1,和字母a为例:
一般验证码数字1字符阵列的定义为,
vNumberDate(0) = "1110000111110111101111011110111101001011110100101111010010111101001011110111101111011110111110000111" ;这样可能看不出什么究竟来但是我们按10*10的阵列来看:
1111011111
1100011111
1111011111
1111011111
1111011111
1111011111
1111011111
1111011111
1111011111
1100000111
不难看出这其中0组成了一个1的形状!我们在看看a的字符阵列:
vNumberData(10) = "1111011111111101111111101011111110101111111010111111101011111100000111110111011111011101111000100011"
1111011111
1111011111
1110101111
1110101111
1110101111
1110101111
1100000111
1101110111
1101110111
1000100011
一个A的形状也出来了,其他的字符也是如此;
明白了上面的原理有设计自己的验证码字符阵列也就简单了!
有了以上的内容作为基础后就可以来分析验证码程序的设计思路了!
验证码程序无非包括两个部分:前台用户看到的图片验证码和与前台用户提交验证码相比较的图片验证码对应的数字类型!所以我们必须分别处理!
数字部分的设计实现比较简单,如下:
Const ValiCodeDate = "0123456789"
Const ValiCodeNum = 9
Dim IndexNum(3),ValidateCode,i,ii,iii,k
For i = 0 to 3
IndexNum(i) = Cint(Rnd * ValiCodeNum)
ValidateCode = ValidateCode&Mid(ValiCodeDate,IndexNum(i) + 1,1)
Next
Session("ValidateCode") = ValidateCode
其中ValiCodeDate定义了验证码的所需字符,ValiCodeNum定义了验证码字符个数,通过For循环产生4位的随机验证码并储存在Session中用于与用户提交数据比较!
前台显示部分如下:
Dim ColorDate(1)
ColorDate(0) = ChrB(0) & ChrB(0) & ChrB(0) '黑色 Response.BinaryWrite ChrB(24) & ChrB(0) & ChrB(0) & ChrB(0) & ChrB(0) & ChrB(0) & ChrB(176) & ChrB(4) &_
ChrB(0) & ChrB(0) & ChrB(18) & ChrB(11) & ChrB(0) & ChrB(0) & ChrB(18) & ChrB(11) &_
ChrB(0) & ChrB(0) & ChrB(0) & ChrB(0) & ChrB(0) & ChrB(0) & ChrB(0) & ChrB(0) &_
ChrB(0) & ChrB(0)
For i = 9 To 0 Step -1
For ii = 0 To 3
For iii = 1 To 10
Response.BinaryWrite ColorDate(Mid(vNumberDate(IndexNum(ii)), i * 10 + iii, 1))
Next
Next
Next
这里我们就要看三个For循环语句了,和上面分析道的图片的长与宽了!上面提到图片的长于宽分别为40px,10px;
我们按40*10画出方格!
(1.91),(10.,91),(1,1)(10.1)储存第一个验证码字符,(10.91),(20.91),)(10,1),(20.1)储存第二个验证码字符,(20,91),(30.,91),(20,1)(30.1)储存第三个验证码字符,(30,91)(40,91)(30,1)(40,1)储存第四个验证码字符
我们看这一句:ColorDate(Mid(vNumberDate(IndexNum(ii)), i * 10 + iii, 1))
我们知道ColorDate只有0和1,Mid(vNumberDate(IndexNum(ii)), i * 10 + iii, 1)并且返回的为vNumberDate数组中的值也为0和1;我们看循环
For i = 9 To 0 Step -1
For ii = 0 To 3
For iii = 1 To 10
Response.BinaryWrite ColorDate(Mid(vNumberDate(IndexNum(ii)), i * 10 + iii, 1))
Next
Next
Next
知道程序先小从第十行从左到右分别写入四个字符的91到100位的数据,然后转到第九行分别写入四个字符的81到90位的数据,依次完成整个图片的输出!至此真个图片输出完成!
到此整个验证码程序点的设计也完成了!