天天看点

比较全面的php session验证码与防识别

验证码开发过程中的 3 个误区:

1、  背景干扰:干扰线、干扰点、干扰图,基本没有,程序很容易通过高亮度调节去除掉。

2、  字符旋转:破解机器人通过数次学习、旋转之后,能够得到 90% 以上的正确识别率,采用常规字体,能够得到接近 100% 的识别。

3、  随机间距:基本没用,采用提取高亮度之后,采用图片切割的方法,很容易就将随机间距消灭掉。

防止被破解:

1、  背景干扰线尽量能够干扰到字符,采用和字符相同的颜色,能够破坏高亮度反差色提取法对字符的学习。 qq有采用。

2、  矢量变形:想 google 、 ms 、 yahoo 都采用了这种变态的方法,这种将字符进行扭曲变形,基本上机器识别率为零,因为没有相对应的固定形状。 损失是用户也不一定认得。需要验证码图片有一些大才行。

3、  字符粘连,可以破坏掉字符切割法分割字符, google 也有用到这个, qq 也有采用。

4、  中文验证码,中文验证码的识别难度比较大,但是现在逐渐的也慢慢被学习并且破解。(香港,台湾是用繁体)

5、  字符旋转:需要和字符粘连在一起才能够起作用,他们一起,验证码几乎不具备机器破解可能性。 加随机背景图片、随机字体、稍微旋转字母或数字,位置不固定,稍微扭曲

注意:下载空心字体

字体.ttf的当$mode=7的该字体必须支持中文,否则出现乱码。

在服务端做验证时取session存储的验证字符与用户提交的字符进行比较,相同则通过验证。

比较全面的php session验证码与防识别

<?php  

/* 

* @date 2011-2-24 

* @author hudeyong926 

*/  

function getcode($length = 32, $mode = 0) {  

    switch ($mode) {  

        case '1' :  

            $str = '123456789';  

            break;  

        case '2' :  

            $str = 'abcdefghijklmnopqrstuvwxyz';  

        case '3' :  

        case '4' :  

            $str = 'abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz';  

        case '5' :  

            $str = 'abcdefghijklmnpqrstuvwxyz123456789';  

        case '6' :  

            $str = 'abcdefghijklmnopqrstuvwxyz1234567890';  

        case '7' ://中文验证码  

        default :  

            $str = 'abcdefghijklmnpqrstuvwxyzabcdefghijkmnpqrstuvwxyz23456789';  

    }  

    $result = '';  

    for($i = 0; $i < $length; $i ++) {  

        if ($mode == 7) {  

            $str [$i] = chr ( mt_rand ( 176, 215 ) ) . chr ( mt_rand ( 161, 249 ) );  

            $str [$i] = iconv ( "gb2312", "utf-8", $str [$i] ); //imagettftext是utf-8的,所以先转换下  

            $result .= $str [$i];  

        } else {  

            $l = strlen ( $str ) - 1;  

            $num = mt_rand ( 0, $l );  

            $result .= $str [$num];  

        }  

    return $result;  

}  

//建立验证图片  

function createauthnumimg($randstr, $fontname, $imgw = 100, $imgh = 40) {  

    header ( "content-type: image/png" );  

    $image = imagecreate ( $imgw, $imgh );  

    $fontsize = 20;//字号  

    //$green = imagecolorallocate($image,0x6b,0xc1,0x46);  

    $gray = imagecolorallocate ( $image, 228, 228, 228 ); //灰色  

    $red  = imagecolorallocate ( $image, 255, 102, 204 );//粉色   

    $blue = imagecolorallocate($image,0x53,0x68,0xbd);  

    $colors = array($red, $gray, $blue);  

    $color_b = imagecolorallocate ( $image, 0, 0, 0 ); //黑色  

    for($i = 0; $i < 1000; $i ++) { //绘背景干扰点  

        imagesetpixel ( $image, mt_rand ( 0, $imgw ), mt_rand ( 0, $imgh ), $colors[rand(0,count($colors)-1)]);  

    imagerectangle ( $image, 0, 0, $imgw - 1, $imgh - 1, $color_b );//绘制边框  

    imagettftext ( $image, $fontsize, 5, 3, 25, $color_b, $fontname, $randstr);///将验证字符绘入图片 字符旋转      

    for($i=0; $i<2; $i++){ //绘背景干扰线  

        imageline($image, mt_rand(0,5), mt_rand(6,18), mt_rand(65,$imgw), mt_rand(6,$imgh), $color_b);//一条干扰线  

    }     

    imagepng ( $image );  

    imagedestroy ( $image );  

session_start ();  

$verifycode = getcode ( 5 );  

$_session ['verify_code'] = $verifycode ;  

createauthnumimg ( $verifycode, "font.ttf", 75, 30); //字体存放路径,如果你没有文件就去c:\windows\fonts文件中找一个吧。  

/** 问答模式 

$a=getcode(2,1);   

$b=getcode(1,1);   

$passport = $a."+".$b."=?";   

$verifycode = $a+$b;   

$_session ['verify_code'] = $verifycode ;   

createauthnumimg ( $passport, "font.ttf", 75, 30); 

?>  

中文占两个字符长度,需要控制验证码图片的长度,一个中文位置相当于2个非中文

比较全面的php session验证码与防识别

<?php echo strlen('中'); echo strlen('ad');?>  

为了避免机器人的破解,验证码的视觉效果越来越差,随之很多网站就加了“看不清?请刷新”之类的功能,当然也不是简简单单的页面刷新,是只刷新验证码部分,用户从而得到一个新的验证码。在网上看了些别人写的方法,下面总结两种。

第一种比较简单,运用一下onclick即可,直接点击验证码的图片就可以刷新,不过最好在验证码后面说明一下,提示有这个功能。

比较全面的php session验证码与防识别

<img src="validimg.jsp" alt="看不清?请刷新" width="50" height="20" onclick="this.src=this.src+'?'+math.random()" />  

比较全面的php session验证码与防识别

<img src="validimg.jsp" width="50" height="20" > <a href="javascript:reloadimage("validimg.jsp" );">刷新</a>  

<script language="javascript">  

function reloadimage(url){  

document.formname.img1.src = url+math.random();  

</script>