在PHP网站开发中,验证码可以有效地保护我们的表单不被恶意提交,但是如果不使用算式验证码或者汉字验证码,仅仅使用简单的字母或者数字验证码,这样的验证码方案真的安全吗?
大家知道简单数字或者字母验证码很容易被破解,但是算式验证码或者中文汉字验证码不容易被破解,所以建议大家在使用验证码的时候,尽量用算式验证码或者中文汉字验证码。
下面是两种验证码代码,有用到的朋友可以参考下:
1.算式验证码:
<?php session_start(); header("Content-type: image/png"); $num1 = mt_rand(0,9);//第一位数 $num2 = mt_rand(1,9);//第二位数 $type_str = "+-*";//方法字符串集合 $type = substr($type_str,rand(0,2),1);//随机方法 $change = mt_rand(1,3); if($change==1){ $code = "$num1$type$num2=?"; $result = "\$verifyCode=$num1$type$num2;"; eval($result); $_SESSION['authnum_session'] = $verifyCode; }elseif($change==2){ $result = "\$verifyCode=$num1$type$num2;"; eval($result); $code = $num1.$type."_=".$verifyCode; $_SESSION['authnum_session'] = $num2; }elseif($change==3){ $result = "\$verifyCode=$num1$type$num2;"; eval($result); $code = "_".$type.$num2."=".$verifyCode; $_SESSION['authnum_session'] = $num1; } $im = imagecreate(68,28); $black = imagecolorallocate($im, 0,0,0); $white = imagecolorallocate($im, 255,255,255); $gray = imagecolorallocate($im, 200,200,200); $red = imagecolorallocate($im, 255, 0, 0); imagefill($im,0,0,$white); imagestring($im, 5, 10, 8, $code, $black); for($i=0;$i<70;$i++) { imagesetpixel($im, mt_rand(0, 58) , mt_rand(0, 28) , $black); imagesetpixel($im, mt_rand(0, 58) , mt_rand(0, 28) , $red); imagesetpixel($im, mt_rand(0, 58) , mt_rand(0, 28) , $gray); } imagepng($im); imagedestroy($im); ?>
2.中文汉字验证码:
<?php session_start(); $ch_str="的一是在了不和有大这主中人上为们地个用工时要动国产以我到他会作来分生对于学下级就年阶义发成部民可出能方进 同行面说种过命度革而多子后自社加小机也经力线本电高量长党得实家定深法表着水理化争现所二起政三好十战无农使性前等反 体合斗路图把结第里正新开论之物从当两些还天资事队批如应形想制心样干都向变关点育重其思与间内去因件日利相"; $len = mb_strlen($ch_str,"utf-8");//汉字长度 $str = array(); for($i=0;$i<4;$i++){ $pos = mt_rand(0,$len-5);//开始位置 $str[] = mb_substr($ch_str,$pos,1,"utf-8"); } $authnum_session = implode("",$str); $_SESSION['authnum_session'] = $authnum_session; //记录到session Header("Content-type: image/PNG"); //图片的长和高 $image_x=100; $image_y=50; $im = imagecreate($image_x,$image_y); //这里取图片底色为白色 $bkg = ImageColorAllocate($im,255,255,255); //显示的字体样式,这个要把文件放到对应的目录中,如果你没有文件就去window的字体文件中找一个吧。 $fnt = "simhei.ttf"; //为图像分配一些颜色 $white=ImageColorAllocate($im,234,185,95); //在图片上画椭圆弧,指定下坐标点 imagearc($im, 150, 8, 20, 20, 75, 170, $white); imagearc($im, 180, 7,50, 30, 75, 175, $white); //在图片上画一条线段,指定下坐标点 imageline($im,20,20,180,30,$white); imageline($im,20,18,170,50,$white); imageline($im,25,50,80,50,$white); //乱点的数量 $noise_num=3000; $line_num=50; //各种混乱字符的颜色 $rectangle_color=imagecolorallocate($im,0xAA,0xAA,0xAA); $noise_color=imagecolorallocate($im,0x00,0x00,0x00); $font_color=imagecolorallocate($im,0x00,0x00,0x00); for($i=0;$i<$noise_num;$i++) { //在一个坐标点上画一个单一像素,这个点上面定义了,是黑色的。 //imagesetpixel($im,mt_rand(0,$image_x),mt_rand(0,$image_y),$noise_color); } for($i=0;$i<$line_num;$i++) { $line_color=imagecolorallocate($im,mt_rand(0,255),mt_rand(0,255),mt_rand(0,255)); //在两个坐标点间画一条线,颜色在上面定义 imageline($im,mt_rand(0,$image_x),mt_rand(0,$image_y),mt_rand(0,$image_x),mt_rand(0,$image_y),$line_color); } for ($i=0;$i<4;$i++) { ImageTTFText($im, rand(18,20), rand(0,20), rand(($image_x/4)*$i+$image_x/100,($image_x/4)*$i+$image_x/8), rand($image_y/2+$image_y/10,$image_y/2+$image_y/5), $font_color, $fnt, $str[$i]); } ImagePNG($im); ImageDestroy($im); ?>
注意:
中文汉字验证码单独执行,然后获取session会发现验证码和session内容不一致。但是在img 标签中src属性中引用这个中文汉字验证码文件时,然后获取session,这时两者内容时一致的。
感兴趣的朋友可以对此进一步加以完善。