`
baobaoupup
  • 浏览: 471097 次
文章分类
社区版块
存档分类
最新评论

改进的php验证码生成程序

 
阅读更多

上一篇文章说的验证码生成,最后得到的程序在使用中你会发现有个问题,就是生成的验证码有时会不好辨认。干扰线越多情况就越严重。如下图:

(5条干扰线的效果)

(10条干扰线的效果)

其中的第2个数字是1还是7,不太好辨认。我实验了一下生成的容易分辨的验证码大概在80% - 90%间。

如果去除干扰线效果就好很多,基本都能辨认出来。但是图片简单了容易让别人使用程序给识别出来。不是好办法。,再分析一下原因其实就是干扰点和干扰线实在画完数字后再画上的,这样就对原图片上的数字产生了遮挡。如果先生成干扰点和干扰线再画上图片的话效果应该会好很多。我猜想,这么实现呢?使用我上一篇的程序,调整一下语句的顺序让数字在干扰点线后生成,呵呵,这样显然不行,因为我是用产生的数字图片贴上背景图实现的,因此有个数字的背景问题,他的白色背景会覆盖原图。效果如下:

显然这结果不太好,有一种简单的方法就是放弃使用旋转而直接画出数字,那得出的效果就是规规矩矩的数字图片了,也使得使用程序辨认难度降低。也不太好。

其实要解决也不太难,只要将数字的白色背景加以扣除就行了。再使用带透明度的拷贝函数拷贝到背景图片上就可以了(就是imagecopymerge函数),于是就得到以下程序(完整的代码):


header("Pragma: no-cache");
header("Cache-Control: max-age=1, s-maxage=1, no-cache, must-revalidate");
session_start();
unset($_SESSION['validate']);

$randStr = array(rand(0, 9), rand(0, 9), rand(0, 9), rand(0, 9));// 产生4个随机字符
$_SESSION['validate'] = $randStr[0].$randStr[1].$randStr[2].$randStr[3];

function RgbToHsv($R, $G, $B)
{
$tmp = min($R, $G);
$min = min($tmp, $B);
$tmp = max($R, $G);
$max = max($tmp, $B);
$V = $max;
$delta = $max - $min;

if($max != 0)
$S = $delta / $max; // s
else
{
$S = 0;
//$H = UNDEFINEDCOLOR;
return;
}
if($R == $max)
$H = ($G - $B) / $delta; // between yellow & magenta
else if($G == $max)
$H = 2 + ($B - $R) / $delta; // between cyan & yellow
else
$H = 4 + ($R - $G) / $delta; // between magenta & cyan

$H *= 60; // degrees
if($H < 0)
$H += 360;
return array($H, $S, $V);
}

function HsvToRgb($H, $S, $V)
{
if($S == 0)
{
// achromatic (grey)
$R = $G = $B = $V;
return;
}

$H /= 60;// sector 0 to 5
$i = floor($H);
$f = $H - $i;// factorial part of h
$p = $V * (1 - $S);
$q = $V * (1 - $S * $f);
$t = $V * (1 - $S * (1 - $f));

switch($i)
{
case 0:
$R = $V;
$G = $t;
$B = $p;
break;
case 1:
$R = $q;
$G = $V;
$B = $p;
break;
case 2:
$R = $p;
$G = $V;
$B = $t;
break;
case 3:
$R = $p;
$G = $q;
$B = $V;
break;
case 4:
$R = $t;
$G = $p;
$B = $V;
break;
default: // case 5:
$R = $V;
$G = $p;
$B = $q;
break;
}
return array($R, $G, $B);
}

$size = 20;
$width = 80;
$height = 25;
$degrees = array(rand(0, 45), rand(0, 45), rand(0, 45), rand(0, 45));// 生成数字旋转角度

for($i = 0; $i < 4; ++$i)
{
if(rand() % 2);
else $degrees[$i] = -$degrees[$i];
}

$image = imagecreatetruecolor($size, $size);// 数字图片画布
$validate = imagecreatetruecolor($width, $height);// 最终验证码画布
$back = imagecolorallocate($image, 255, 255, 255);// 背景色
$border = imagecolorallocate($image, 0, 0, 0);// 边框
imagefilledrectangle($validate, 0, 0, $width, $height, $back);// 画出背景色

// 数字颜色
for($i = 0; $i < 4; ++$i)
{
// 考虑为使字符容易看清使用颜色较暗的颜色
$temp = RgbToHsv(rand(0, 255), rand(0, 255), rand(0, 255));

if($temp[2] > 60)
$temp [2] = 60;

$temp = HsvToRgb($temp[0], $temp[1], $temp[2]);
$textcolor[$i] = imagecolorallocate($image, $temp[0], $temp[1], $temp[2]);
}

for($i = 0; $i < 200; ++$i) //加入干扰象素
{
$randpixelcolor = ImageColorallocate($validate, rand(0, 255), rand(0, 255), rand(0, 255));
imagesetpixel($validate, rand(1, 87), rand(1, 27), $randpixelcolor);
}

// 干扰线使用颜色较明亮的颜色
$temp = RgbToHsv(rand(0, 255), rand(0, 255), rand(0, 255));

if($temp[2] < 200)
$temp [2] = 255;

$temp = HsvToRgb($temp[0], $temp[1], $temp[2]);
$randlinecolor = imagecolorallocate($image, $temp[0], $temp[1], $temp[2]);

// 画5条干扰线
for ($i = 0;$i < 5; $i ++)
imageline($validate, rand(1, 79), rand(1, 24), rand(1, 79), rand(1, 24), $randpixelcolor);

imagefilledrectangle($image, 0, 0, $size, $size, $back);// 画出背景色
imagestring($image, 5, 6, 2, $randStr[0], $textcolor[0]);// 画出数字
$image = imagerotate($image, $degrees[0], $back);
imagecolortransparent($image, $back);
imagecopymerge($validate, $image, 1, 4, 4, 5, imagesx($image) - 10, imagesy($image) - 10, 100);

$image = imagecreatetruecolor($size, $size); // 刷新画板
imagefilledrectangle($image, 0, 0, $size, $size, $back);// 画出背景色
imagestring($image, 5, 6, 2, $randStr[1], $textcolor[1]);// 画出数字
$image = imagerotate($image, $degrees[1], $back);
imagecolortransparent($image, $back);
imagecopymerge($validate, $image, 21, 4, 4, 5, imagesx($image) - 10, imagesy($image) - 10, 100);

$image = imagecreatetruecolor($size, $size); // 刷新画板
imagefilledrectangle($image, 0, 0, $size - 1, $size - 1, $back);// 画出背景色
imagestring($image, 5, 6, 2, $randStr[2], $textcolor[2]);// 画出数字
$image = imagerotate($image, $degrees[2], $back);
imagecolortransparent($image, $back);
imagecopymerge($validate, $image, 41, 4, 4, 5, imagesx($image) - 10, imagesy($image) - 10, 100);

$image = imagecreatetruecolor($size, $size); // 刷新画板
imagefilledrectangle($image, 0, 0, $size - 1, $size - 1, $back);// 画出背景色
imagestring($image, 5, 6, 2, $randStr[3], $textcolor[3]);// 画出数字
$image = imagerotate($image, $degrees[3], $back);
imagecolortransparent($image, $back);
imagecopymerge($validate, $image, 61, 4, 4, 5, imagesx($image) - 10, imagesy($image) - 10, 100);

imagerectangle($validate, 0, 0, $width - 1, $height - 1, $border);// 画出边框

header('Content-type: image/png');
imagepng($validate);
imagedestroy($validate);
imagedestroy($image);

?>

这个程序得到的效果还是比较理想的。你还可以多加几条干扰线也没问题,经实验生成的容易识别的验证码基本上能达到100%

运行后的效果如下:

(5条干扰线的效果)

(10条干扰线的效果)

你会发现以上两幅图很容易就能辨认出是7115和3179。

如果使用较粗的字体干扰素和干扰线可以使用任意颜色,而不用处理也能得到较好的效果,在不引起歧义的情况下(比如除去某些些数字)可以考虑加大数字的旋转角度,如果要使程序更难辩认可以不使用旋转,考虑其他算法。

另外ImageColorAt和imagesetpixel函数结合使用,还可以对点进行操作,比如将单色数字变花色数字,甚至可以进行正弦曲线Wave扭曲图片等操作。

还有要说明的就是使用机器识别这方法产生的验证码不是不可能的。而生成验证码的程序应该是满足使用最简单的办法达到比较好的效果就是是最佳选择,我并不要求生成的识别码,机器100%不能识别(包括recaptcha这玩意据说有俄罗斯的人用机器识别出来了,但识别率很低)。其实只要做到10000次里机器只能正确识别一次,这样就可以了,因为这东西只是防止机器发大量的垃圾信息使用,并不能防止人工操作。也就是说我自要把机器识别的效率降到人工效率就达到目的了。

分享到:
评论

相关推荐

    PHP网络编程技术与实践 源码

    13.4 改进的分页显示模块 13.5 本章小结 第14章 计数器模块 14.1 文本计数器 14.2 图形计数器 14.3 防止刷新的计数器 14.4 本章小结 第15章 邮件发送模块 15.1 使用mail函数发送邮件 15.2 使用管道的形式发送邮件 ...

    php网络开发完全手册

    11.3.5 改进的用户信息输入程序 178 11.4 URL编码解码函数 181 11.4.1 编码字符串——urlencode 181 11.4.2 解码字符串——urldecode 181 11.5 小结 182 第12章 PHP与JavaScript交互 183 12.1 JavaScript简介 183 ...

    帝国下载系统 v2.5 开源正式版 bulid 090613.rar

    24、验证码改进,增加图片增加干扰字符。防止机器识别图片字符。 25、安全性方面更强: (1)、管理员密码采用双重md5模式,防止密码泄漏被暴力破解; (2)、登录新增认证码功能,要同时满足密码跟认证码同时正确...

    Z-BlogPHP v1.3 正式版.rar

    Z-BlogPHP是一款简单,快速,高效的PHP博客程序 Z-BlogPHP 有着丰富和强大的可定制性,做为CMS系统使用,Z-BlogPHP可以更方便的管理和扩展您的网站。 Z-BlogPHP可以运行在Windows,Linux等众多**台上,支持Apache,...

    帝国下载系统 v2.5 开源正式版 bulid 090613

    24、验证码改进,增加图片增加干扰字符。防止机器识别图片字符。 25、安全性方面更强: (1)、管理员密码采用双重md5模式,防止密码泄漏被暴力破解; (2)、登录新增认证码功能,要同时满足密码跟认证码同时正确才能...

    DJCMS影视程序(开源) v3.0 build 20110808

    8.改进生成选项的体验,无效的变灰,比如动态模式下,部分生成按钮变灰. 9.新增数据回收站,单个数据隐藏后进入回收站、前台无法显示 10.新增数据字段:语言、导演 11.分类管理,支持单个分类的关键词和描述设置 12....

    帝国下载系统 v2.5 开源正式版 bulid 090416.rar

    24、验证码改进,增加图片增加干扰字符。防止机器识别图片字符。 25、安全性方面更强: (1)、管理员密码采用双重md5模式,防止密码泄漏被暴力破解; (2)、登录新增认证码功能,要同时满足密码跟认证码同时正确...

    建站之星(sitestar)网站建设系统体验包 v2.3.rar

    它一改过去传统的企业建站方式,不需企业编写任何程序或网页,无需学**任何相关语言,也不需第三方代写或管理网站,只需应用系统所提供的各种强大丰富的功能模块,即可轻松生成企业个性化的精美网站。 SiteStar网站...

    EmpireCMS程序源码开源 5.1 GBK

    19、验证码改进,增加图片增加干扰字符。防止机器识别图片字符。 修复: 20、修复批量发送邮件编码问题。 21、修复统计信息标签为只统计审核信息数,并改进算法。 22、修复内容模板不支持调用静态评分标签。 23、...

    EmpireCMS程序源码开源 5.1 UTF8

    19、验证码改进,增加图片增加干扰字符。防止机器识别图片字符。 修复: 20、修复批量发送邮件编码问题。 21、修复统计信息标签为只统计审核信息数,并改进算法。 22、修复内容模板不支持调用静态评分标签。 23、...

    JAVA上百实例源码以及开源项目源代码

    有添加图片水印和文字水印,可以设置水印位置,透明度、设置对线段锯齿状边缘处理、水印图片的路径,水印一般格式是gif,png,这种图片可以设置透明度、水印旋转等,可以参考代码加以改进做成小工具。 Java右键弹出...

    DjCms电影管理系统 3.0 build 20110808

    8.改进生成选项的体验,无效的变灰,比如动态模式下,部分生成按钮变灰 9.新增数据回收站,单个数据隐藏后进入回收站、前台无法显示 10.新增数据字段:语言、导演 12分类管理,支持单个分类的关键词和描述设置 13...

    EmpireCMS 5.1程序源码繁体开源 BIG5

    19、验证码改进,增加图片增加干扰字符。防止机器识别图片字符。 修复: 20、修复批量发送邮件编码问题。 21、修复统计信息标签为只统计审核信息数,并改进算法。 22、修复内容模板不支持调用静态评分标签。 23、...

    EmpireCMS 5.1程序源码开源繁体 UTF8

    19、验证码改进,增加图片增加干扰字符。防止机器识别图片字符。 修复: 20、修复批量发送邮件编码问题。 21、修复统计信息标签为只统计审核信息数,并改进算法。 22、修复内容模板不支持调用静态评分标签。 23、...

    JAVA上百实例源码以及开源项目

    有添加图片水印和文字水印,可以设置水印位置,透明度、设置对线段锯齿状边缘处理、水印图片的路径,水印一般格式是gif,png,这种图片可以设置透明度、水印旋转等,可以参考代码加以改进做成小工具。 Java右键弹出...

    帝国网站管理系统 v6.0简体GBK

    模板LIST.VAR支持程序代码:使帝国所有模板均可使用php代码对字段内容进行灵活处理,实现各种复杂应用。 新增标题分类功能 新增购买充值类型功能 结合项功能全面升级,检索范围更大更灵活 防发贴机的验证码算法 会员...

    帝国网站管理系统 v6.0简体UTF8

    模板LIST.VAR支持程序代码:使帝国所有模板均可使用php代码对字段内容进行灵活处理,实现各种复杂应用。 新增标题分类功能 新增购买充值类型功能 结合项功能全面升级,检索范围更大更灵活 防发贴机的验证码算法 会员...

    VeryIDE Bee 互动营销**台 v1.5 UTF-8.rar

    修正 专题不能生成多页面的问题,感谢 吴越在线 提交问题 修正 各浏览器中"漂浮广告"的表现,感谢 吴越在线 提交问题 修正 投票子选项在被禁用时仍能继续统计的问题,感谢 吴越在线 提交问题 修正 Flash 在没有...

    鑫路在线竞价订单管理系统

    注:需使用【产品分类】里的生成iframe代码方能生效(或设置iframe的ID为buyiframe亦可生效); 5、添加检测快递号是否重复使用; 6、添加自动计算并显示不同支付方式分别优惠多少钱 7、去掉订单搜索时必须选定搜索...

Global site tag (gtag.js) - Google Analytics