这次接着上次的浅谈验证码继续讲:
注意,以为最近都在用PHP,因此本文的代码主要以PHP为主
1.先来一段最简单的,字母加数字,然后纯色背景。
专门建立个code,php来写,之后的代码都是写在这个文件里
<?php
//去掉了容易混淆的字符oOLl和数字01
//例子中只产生4个字符长度的字符串
$code_len = 4;
$width = 60;
$height = 25;
$type = "png";//图片类型,貌似只能支持png gif和jpeg
$chars='ABCDEFGHIJKMNPQRSTUVWXYZabcdefghijkmnpqrstuvwxyz23456789';
$len = strlen($chars);
$chars = str_shuffle($chars);
$code = substr($chars,mt_rand(0,$len - $code_len),$code_len);//随机打乱,然后随机的截取连续的字符
if ( $type!='gif' && function_exists('imagecreatetruecolor')) {
$img = @imagecreatetruecolor($width,$height);
}else {
$img = @imagecreate($width,$height);
}
$bg_color = imagecolorallocate($img, 155,155,155);//背景颜色
$code_Color = imagecolorallocate($img,0,0,0);//字符颜色
@imagefilledrectangle($img, 0, 0, $width - 1, $height - 1, $bg_color);//填充背景
@imagestring($img, 5, 5, 3, $code, $code_color);
header("Content-type: image/".$type);//这样,浏览器就可以直接显示图片了
$image_func='Image'.$type;//颜色输出函数
$image_func($img);
imagedestroy($img);
?>
结果如下:
好吧,这种简单的哄小孩子的验证码几乎让人笑死了,但是,很多国内的网站,比如一些政府机关的网站,就是用的这类验证码。。。
2.好吧,那么,提高下识别难度,加入噪声点和线,当然,也是简单的
至于字符还有背景的颜色,也可以加入随机的,不像上面那种纯色单一不变的。
$bg_color = imagecolorallocate($img, mt_rand(100,240),mt_rand(100,240),mt_rand(100,240));//背景颜色
$code_Color = imagecolorallocate($img,mt_rand(0,200),mt_rand(0,150),mt_rand(0,150));//字符颜色
@imagefilledrectangle($img, 0, 0, $width - 1, $height - 1, $bg_color);//填充背景
//画点
for($i=0;$i<100;$i++){
$fontcolor=imagecolorallocate($img,mt_rand(0,255),mt_rand(0,255),mt_rand(0,255));
imagesetpixel($img,mt_rand(0,$width),mt_rand(0,$height),$fontcolor);
}
//画直线
for($i=0;$i<10;$i++){
$fontcolor=imagecolorallocate($img,mt_rand(0,255),mt_rand(0,255),mt_rand(0,255));
imageline($img,mt_rand(0,$width),mt_rand(0,$height),mt_rand(0,$width),mt_rand(0,$height),$fontcolor);
}
@imagestring($img, 5, 5, 3, $code, $code_color);
好吧,来看看效果:
嗯,不错吧,看得眼花缭乱的,应该可以了,但是,很遗憾,在破解的人看来,这种验证码跟上面的幼儿级验证码没什么区别,不信?
打开你的PS,阈值化处理下,你会发现:
现在,相信了吧?为啥?噪声的颜色可必须与字符的颜色一样,否则破解的第一步阈值化就搞定你的验证码了。还是拿国内政府机关的网站开涮,如果说上面那种验证码有1%的网站在用的话,用这样的验证码的网站也几乎是10%在用(纯猜测,只是来举个例子而已)
3.那么,现在加入同样颜色的噪声,为方便起见,我就用白色背景以及黑色字符
$bg_color = imagecolorallocate($img, 255,255,255);//背景颜色
@imagefilledrectangle($img, 0, 0, $width - 1, $height - 1, $bg_color);//填充背景
$code_Color = imagecolorallocate($img,0,0,0);//字符颜色
@imagestring($img, 5, 5, 3, $code, $code_color);
//画点
for($i=0;$i<70;$i++){
imagesetpixel($img,mt_rand(0,$width),mt_rand(0,$height),$code_Color);
}
//画直线
for($i=0;$i<2;$i++){
imageline($img,mt_rand(0,$width),mt_rand(0,$height),mt_rand(0,$width),mt_rand(0,$height),$code_Color);
}
可以调整下噪声数量,太多了就连人都看不清了
现在,这种验证码可以难倒一部分菜鸟级的黑客破解了,好吧,为了应付破解高手,咱还得提高破解难度
4.我们现在加入高级的字体,以及字符的旋转以及重叠
<?php
//去掉了容易混淆的字符oOLl和数字01
//例子中只产生4个字符长度的字符串
$code_len = 4;
$width = 140;
$height = 50;
$type = "png";//图片类型
$font = "fpnf.ttf";//字体文件,放在同目录下
$chars='ABCDEFGHIJKMNPQRSTUVWXYZabcdefghijkmnpqrstuvwxyz23456789';
$len = strlen($chars);
$chars = str_shuffle($chars);
$code = substr($chars,mt_rand(0,$len - $code_len),$code_len);//随机打乱,然后随机的截取连续的字符
if ( $type!='gif' && function_exists('imagecreatetruecolor')) {
$img = @imagecreatetruecolor($width,$height);
}else {
$img = @imagecreate($width,$height);
}
$bg_color = imagecolorallocate($img, 255,255,255);//背景颜色
@imagefilledrectangle($img, 0, 0, $width - 1, $height - 1, $bg_color);//填充背景
$code_Color = imagecolorallocate($img,0,0,0);//字符颜色
//@imagestring($img, 5, 5, 3, $code, $code_color);
for($i=0;$i<$code_len;$i++){
imagettftext($img,mt_rand(25,30),mt_rand(-45,45),30*$i+10,mt_rand(30,35),$code_Color,$font,substr($code,$i,1));
}
//画点
for($i=0;$i<200;$i++){
imagesetpixel($img,mt_rand(0,$width),mt_rand(0,$height),$code_Color);
}
//画直线
for($i=0;$i<10;$i++){
imageline($img,mt_rand(0,$width),mt_rand(0,$height),mt_rand(0,$width),mt_rand(0,$height),$code_Color);
}
header("Content-type: image/".$type);//这样,浏览器就可以直接显示图片了
$image_func='Image'.$type;//颜色输出函数
$image_func($img);
imagedestroy($img);
?>
来看看效果:
效果不错吧,这里用的字体写入函数是 imagettftext ,链接在此:http://cn2.php.net/manual/zh/function.imagettftext.php
它有更多高级的选项,比imagestring高级,也更灵活,可以实现字体的旋转和重叠,至于字体,为了提高破解难度,可以试试手写字体
好了,就到这,其它更高级的下次有机会再说~