电脑故障

位置:IT落伍者 >> 电脑故障 >> 浏览文章

验证码技术及其实现


发布日期:2018/11/23
 

不少网站为了防止用户利用机器人自动注册登录灌水都采用了验证码技术所谓验证码就是将一串随机产生的数字或符号生成一幅图片图片里加上一些干扰象素(防止OCR)由用户肉眼识别其中的验证码信息输入表单提交网站验证验证成功后才能使用某项功能
PHP实现
我们这里展示了如何编写PHP程序实现验证码功能

代码一

<?php
/*
* Filename:authpagephp
* Author: hutuworm
* Date:
* @Copylefthutuwormorg
*/

srand((double)microtime()*);

//验证用户输入是否和验证码一致
if(isset($HTTP_POST_VARS[authinput]))
{
if(strcmp($HTTP_POST_VARS[authnum]$HTTP_POST_VARS[authinput])==)

echo "验证成功!";
else
echo "验证失败!";
}

//生成新的四位整数验证码
while(($authnum=rand()%)<);
?>
<form action=authpagephp method=post>
<table>
请输入验证码<input type=text name=authinput style="width:
px"><br>
<input type=submit name="验证" value="提交验证码">
<input type=hidden name=authnum value=<? echo $authnum; ?>>
<img src=authimgphp?authnum=<? echo $authnum; ?>>
</table>
</form>

代码二

<?php
/*
* Filename:authimgphp
* Author: hutuworm
* Date:
* @Copylefthutuwormorg
*/

//生成验证码图片
Header("Contenttype: image/PNG");
srand((double)microtime()*);
$im = imagecreate();
$black = ImageColorAllocate($im );
$white = ImageColorAllocate($im );
$gray = ImageColorAllocate($im );
imagefill($im$gray);

//将四位整数验证码绘入图片
imagestring($im $HTTP_GET_VARS[authnum] $black);

for($i=;$i<;$i++) //加入干扰象素
{
imagesetpixel($im rand()% rand()% $black);
}

ImagePNG($im);
ImageDestroy($im);
?>



本文程序在Apache + PHP 环境下运行通过

上文只是对验证码功能的一个简单实现并没有考虑商用安全性问题如果要增强安全性将此功能投入商业应用则可以通过以下几个步骤实现

启用Session
authnum在authimgphp中生成并计算mdsum存入session

authpagephp将authinput计算mdsum后与session中的authnum(mdsum)对比得出验证结果


本站注作者使用了简单的代码实现了很酷的功能不过在添加干扰像素时的效果不是太好大家可以看一下雨声论坛登录时的效验码偶把第二段代码稍改了一下生成了与其类似的效果

修改后的代码如下

<?php
/*
* Filename: authimgphp
* Author: hutuworm
* Date:
* @Copyleft hutuwormorg
*/
//生成验证码图片
Header("Contenttype: image/PNG");
srand((double)microtime()*);
$im = imagecreate();
$black = ImageColorAllocate($im );
$white = ImageColorAllocate($im );
$gray = ImageColorAllocate($im );
imagefill($im$gray);
while(($authnum=rand()%)<);
//将四位整数验证码绘入图片
imagestring($im $authnum $black);
for($i=;$i<;$i++) //加入干扰象素
{
$randcolor =
ImageColorallocate($imrand()rand()rand());
imagesetpixel($im rand()% rand()% $randcolor);
}
ImagePNG($im);
ImageDestroy($im);
?>
显示结果如下图
[在新窗口中浏览该图片]

有兴趣的朋友可以自己试一下

看一下上面这段代码
第一次看PHP代码呵呵奇怪的学习经历


代码一

<?php
/*
* Filename:authpagephp
* Author: hutuworm
* Date:
* @Copylefthutuwormorg
*/

//以系统时间为种子得到随机数
//srand 播下随机数发生器种子
//microtime 返回当前 UNIX 时间戳和微秒数

srand((double)microtime()*);

//验证用户输入是否和验证码一致
if(isset($HTTP_POST_VARS[authinput]))
{
//authnum的值是不应该发送到客户端的这里应该是为了构建一个简单的例子先吧
//authnum 保存在session 里应该是个可行的办法

if(strcmp($HTTP_POST_VARS[authnum]$HTTP_POST_VARS[authinput])==)

echo "验证成功!";
else
echo "验证失败!";
}

//生成新的四位整数验证码
while(($authnum=rand()%)<);
?>
<form action=authpagephp method=post>
<table>
请输入验证码<input type=text name=authinput style="width:
px"><br>
<input type=submit name="验证" value="提交验证码">
<input type=hidden name=authnum value=<? echo $authnum; ?>>
<img src=authimgphp?authnum=<? echo $authnum; ?>>
</table>
</form>

代码二


<?php
/*
* Filename:authimgphp
* Author: hutuworm
* Date:
* @Copylefthutuwormorg
*/

//下面几行代码肯定会让写ASP的GGDD们羡慕不已

//生成验证码图片

//指定头信息

Header("Contenttype: image/PNG");
srand((double)microtime()*);

//返回一个图像标识符代表了一幅大小为 X 的空白图像
$im = imagecreate();
$black = ImageColorAllocate($im );
$white = ImageColorAllocate($im );
$gray = ImageColorAllocate($im );
imagefill($im$gray);


//强悍!!


//将四位整数验证码绘入图片

//方便起见使可以通过authimgphp?authnum=XXXX的方式得到图片实际应用中这种做法肯定是不足取的

imagestring($im $HTTP_GET_VARS[authnum] $black);

for($i=;$i<;$i++) //加入干扰象素
{
imagesetpixel($im rand()% rand()% $black);
}

ImagePNG($im);
//imagepng 以 PNG 格式将图像输出到浏览器或文件
ImageDestroy($im);
?>



本文程序在Apache + PHP 环境下运行通过

上文只是对验证码功能的一个简单实现并没有考虑商用安全性问题如果要增强安全性将此功能投入商业应用则可以通过以下几个步骤实现

启用Session
authnum在authimgphp中生成并计算mdsum存入session
authpagephp将authinput计算mdsum后与session中的authnum(mdsum)对比得出验证结果


本站注作者使用了简单的代码实现了很酷的功能不过在添加干扰像素时的效果不是太好大家可以看一下雨声论坛登录时的效验码偶把第二段代码稍改了一下生成了与其类似的效果

修改后的代码如下

<?php
/*
* Filename: authimgphp
* Author: hutuworm
* Date:
* @Copyleft hutuwormorg
*/
//生成验证码图片
Header("Contenttype: image/PNG");
srand((double)microtime()*);
$im = imagecreate();
$black = ImageColorAllocate($im );
$white = ImageColorAllocate($im );
$gray = ImageColorAllocate($im );
imagefill($im$gray);
while(($authnum=rand()%)<);
//将四位整数验证码绘入图片
imagestring($im $authnum $black);
for($i=;$i<;$i++) //加入干扰象素
{
$randcolor =
ImageColorallocate($imrand()rand()rand());
imagesetpixel($im rand()% rand()% $randcolor);
}
ImagePNG($im);
ImageDestroy($im);
?>
验证码技术核心内容是动态生成图片ASP做到这一点最简单也是最普遍的就是用到XBM我们先了解一下XBM的相关知识


[转]用XBM创建动态客户端图像

作者 BUILDERCOM
Wednesday April : AM
XBitmap(XBM)是一种古老但通用的图像文件格式它与现在的许多Web浏览器都兼容XWindows图形界面(UNIX和Linux常用的GUI)的C代码库xlib中有一个组件专门描述了它的规范我将解释XBM格式的工作原理然后向你展示一种更有趣的使用它的方法在客户端创建动态图像文章中的代码可以在此下载

XBM基础

XBM格式本来是为存储单色的系统位图而设计的比如图标和鼠标指针XBM图形的实质上是使用进制数组来表示二进制图像的C源代码文件(进制数组表示的二进制图像)

这里你也许会问这种文件格式与Web浏览器有什么关系?在上世纪九十年代早期美国超级计算应用中心(NCSA)在伊利诺斯大学开发第一个被广泛使用的Web浏览器名为Mosaic这个浏览器的图形支持来自很多开放源码代码库其中就包括xlib因此导致今天的许多浏览器能够处理XBM图形

Mosaic项目后来成为了Netscape浏览器的开发基础微软也借用了一部分Mosaic代码来创建Internet Explorer微软继而在网络信息服务器(IIS)中将XBM作为一个MIME类型注册而提供本地支持并且在现有所有版本的Internet Explorer中将其作为一种可支持的图像(浏览器的广泛支持)

从一个程序员的角度来看JPEG或GIF与XBM有着极大的不同这两种文件格式都在位级别上操作并使用了压缩算法它们可以支持很大的颜色深度范围创建这些动态Web图形的唯一方法是使用服务器端的脚本比如<a href=http://steincshlorg/WWW/software/GD/GDpm和CGI/Perl脚本的结合或者通过SystemDrawing名字空间访问ASPNET中的图形设计接口类库(GDI+)(升级到ASPNET有很多个理由)

XBM创建起来很有程序性每个位都被一一指定而结果图形被限制为两色(黑色和白色)(局限性之一让人不爽)XBitmap并不是必须服务器端脚本可以在客户端用JavaScript实时创建它们(增加了不少灵活性)

XBitmap的实用程序包括动态生成的图页面计数器老式图形图标以及统计图表(就是通过位控制太麻烦了有良好的包装就好了另外生成图片的大小算法的强度是否都达到了可用的要求?)给我印象最深的XMB应用是一个叫Wolfensteink的游戏它是一个纹理映射的第一视角射击游戏用JavaScript编写只有KB大小(不错啊稍后爽一下)
通过使用IMG标识可以很容易地将XBM文件嵌入到一个Web页面中其语法如下

<img src=”xbmsmillxbm”>


注意

这种格式不对Mac或相应的浏览器有效比如Mozilla的早期版本



典型的XBM源代码与列表A中显示的比较相像

#define语句以像素点为单位设置了图像的宽度和高度你也可以使用x_hot和y_hot命令来定义图像中的一个热点我已经创建了一个XBitmap来描绘这个过程为了设计它我先将图像映射为二进制值如果你仔细的看在这里你会看到一张笑脸

我所创建的二进制图像宽个数字高个数字在我们的源代码的XBM头中定义了相同大小的宽/高像素值图像本身被存储在一个静态数组中它包含一列二进制编码的十六进制(BCH)值——换句话说每四位分成一组

计算出笑脸的十六进制值得最简单的方法是一次检验图像的一行将二进制值分成四位一组的分段将每个分段映射成二进制/十六进制表中对应的十六进制数下面是第一行



下面两行分别表示四位的分段和其在表A中对应的十六进制数

二进制

十六进制

表A

XBM二/十六进制转换表

二进制十六进制





















A

B

C

D

E

F


请注意这些并不是标准的二/十六进制转换它们是反向计算的(从左到右)而不是从右到左把它颠倒是因为浏览器会从左到右来读图形我们的代码必须与其一致

最后要把这些十六进制值转换成XBM的右格式必须在每个十六进制值前加“x”这是标准C++表示十六进制的方法然后将这些值从右到左输出(每个十六进制对表示八位二进制位)请看列表B中的例子

因此我们可以说

=xx

这些符合XBM的值可以很容易地插入到图像数组中

static unsigned char xbmsmile_bits[]=

现在我们来看看格式本身现在是时候来学习在客户端浏览器中动态创建XBitmap了
图片用点阵的形式表示比如:

为C 即xc
x
x表示十六进制数
依此类推
这是用二进制数得到的点阵其中的为显示一黑点不显示
是一个反着看的
其余数字可自已排列点阵再二进制化为十六进制数
缺点是只有黑白两种颜色
显示出来是白底黑字要显示黑底白字的话对其取反就行了


下面是我"画"的的数字

numasp

<%
Dim a()

a() = "xc" 数字
a() = "x"
a() = "xc"
a() = "xc"
a() = "xc"
a() = "xc"
a() = "xc"
a() = "xc"
a() = "x"
a()= "xc"

a() = "x" 数字
a() = "xc"
a() = "x"
a() = "x"
a() = "x"
a() = "x"
a() = "x"
a() = "x"
a() = "x"
a()= "xe"


a() = "xc" 数字
a() = "x"
a() = "x"
a() = "x"
a() = "x"
a() = "x"
a() = "xc"
a() = "x"
a() = "x"
a()= "xe"

a() = "xc" 数字
a() = "x"
a() = "xc"
a() = "x"
a() = "xc"
a() = "x"
a() = "xc"
a() = "xc"
a() = "x"
a()= "x"

a() = "x" 数字
a() = "xc"
a() = "x"
a() = "x"
a() = "x"
a() = "x"
a() = "xff"
a() = "x"
a() = "x"
a()= "xfe"

a() = "xfe" 数字
a() = "xfe"
a() = "x"
a() = "x"
a() = "xe"
a() = "x"
a() = "xc"
a() = "xc"
a() = "x"
a()= "xc"

a() = "x" 数字
a() = "x"
a() = "x"
a() = "xc"
a() = "xe"
a() = "x"
a() = "xc"
a() = "xc"
a() = "x"
a() ="xc"

a() = "xff" 数字
a() = "xc"
a() = "x"
a() = "x"
a() = "x"
a() = "x"
a() = "x"
a() = "x"
a() = "x"
a()= "x"

a() = "xc" 数字
a() = "x"
a() = "xc"
a() = "x"
a() = "xc"
a() = "x"
a() = "xc"
a() = "xc"
a() = "x"
a()= "xc"

a() = "xc" 数字
a() = "x"
a() = "xc"
a() = "xc"
a() = "x"
a() = "xc"
a() = "x"
a() = "xc"
a() = "x"
a()= "x"

%>

显示的方法是:

先传出一个MIME:
ResponseContentType = "image/xxbitmap"
再传出一个c++的源程序如显示:
#define counter_width
#define counter_height
static unsigned char counter_bits[] = {
xcxxxxxxcxxxe
};
这样在浏览器上就显示出来一个*像素的

要显示两个或以上的数字的时候须改动宽度的值(必须是图像点阵宽度的整数倍)在count_bits[]数组的值排序如下
比如显示
a() a() a() a() a() a()
下面是具体计数器的例子:

countasp

<!#include file="numasp">
<%
Dim Image
Dim Width Height
Dim num
Dim digtal
Dim Length
Dim sort
Length = 自定计数器长度

Redim sort( Length )


num = 计数器的值
digital = ""
For I = To Length Len( num )
digital = digital & ""
Next
For I = To Len( num )
digital = digital & Mid( num I )
Next
For I = To Len( digital )
sort(I) = Mid( digital I )
Next
Width = * Len( digital ) 图像的宽度
Height = 图像的高度在本例中为固定值


ResponseContentType="image/xxbitmap"

hc=chr() & chr()

Image = "#define counter_width " & Width & hc
Image = Image & "#define counter_height " & Height & hc
Image = Image & "static unsigned char counter_bits[]={" & hc

For I = To Height
For J = To Length
Image = Image & a(sort(J)I) & ""
Next
Next

Image = Left( Image Len( Image ) ) 去掉最后一个逗号
Image = Image & "};" & hc

ResponseWrite Image

%>

#define counter_width
#define counter_height
static unsigned char counter_bits[] = {
xcxxxxxxcxxxe
};
保存为 xbm 文件就可以得到一张显示为 的图片


#define counter_width
#define counter_height
static unsigned char counter_bits[]={
xcxcxcxcxcxxcxcxffxfexxxxxxxxxcxfexcxcxcxcxcxxxxxxcxcxcxcxcxcxxxxxcxcxcxcxcxexxxxexcxcxcxcxcxxxxxxcxcxcxcxcxcxcxcxxcxcxcxcxcxcxcxxxxcxxxxxxxxxxxexexexexexcxexexxc};
保存为 xbm文件则显示为

上一篇:使用HMAC-SHA1签名方法详解

下一篇:Memcached常用命令以及使用说明详解