增加动态验证码

jerry thinkphp 2015年11月18日 收藏
增加动态验证码,跳动的验证码增强视觉体验
首先打开Thinkphp官方的Image类文件,默认在ThinkPHP\Extend\Library\ORG\Util下面。
打开找到第405行下面添加(也就是生成图像验证码方法下面),增加一个生成动态验证码的方法。
  1.     /**
  2.      * 生成动态图像验证码
  3.      * @static
  4.      * @access public
  5.      * @param string $length  位数
  6.      * @param string $mode  类型
  7.      * @param string $width  宽度
  8.      * @param string $height  高度
  9.      * @return string
  10.      */
  11.     static function buildActiveImageVerify($length=4, $mode=1, $width=60, $height=22, $verifyName='verify') {
  12.         import('ORG.Util.String');
  13.         import('ORG.Util.GIFEncoder');
  14.         $randval = String::randString($length, $mode);
  15.         session($verifyName, md5($randval));
  16.         $width = ($length * 10 + 10) > $width ? $length * 10 + 10 : $width;
  17.         // 生成一个32帧的GIF动画
  18.         for($i=0;$i<32;$i++){
  19.         ob_start();
  20.         $image=imagecreate($width,$height);
  21.         imagecolorallocate($image,0,0,0);
  22.         // 设定文字颜色数组 
  23.         $colorList[]=ImageColorAllocate($image,15,73,210);
  24.         $colorList[]=ImageColorAllocate($image,0,64,0);
  25.         $colorList[]=ImageColorAllocate($image,0,0,64);
  26.         $colorList[]=ImageColorAllocate($image,0,128,128);
  27.         $colorList[]=ImageColorAllocate($image,27,52,47);
  28.         $colorList[]=ImageColorAllocate($image,51,0,102);
  29.         $colorList[]=ImageColorAllocate($image,0,0,145);
  30.         $colorList[]=ImageColorAllocate($image,0,0,113);
  31.         $colorList[]=ImageColorAllocate($image,0,51,51);
  32.         $colorList[]=ImageColorAllocate($image,158,180,35);
  33.         $colorList[]=ImageColorAllocate($image,59,59,59);
  34.         $colorList[]=ImageColorAllocate($image,0,0,0);
  35.         $colorList[]=ImageColorAllocate($image,1,128,180);
  36.         $colorList[]=ImageColorAllocate($image,0,153,51);
  37.         $colorList[]=ImageColorAllocate($image,60,131,1);
  38.         $colorList[]=ImageColorAllocate($image,0,0,0);
  39.         $fontcolor=ImageColorAllocate($image,0,0,0);
  40.         $gray=ImageColorAllocate($image,245,245,245);
  41.         $color=imagecolorallocate($image,255,255,255);
  42.         $color2=imagecolorallocate($image,255,0,0);
  43.         imagefill($image,0,0,$gray);
  44.         $space=15;// 字符间距
  45.         if($i>0){// 屏蔽第一帧
  46.             $top=0;
  47.             for($k=0;$k<$length;$k++){ 
  48.                 $colorRandom=mt_rand(0,sizeof($colorList)-1);
  49.                 $float_top=rand(0,4);
  50.                 $float_left=rand(0,3);
  51.                 imagestring($image,6,$space*$k,$top+$float_top,substr($randval,$k,1),$colorList[$colorRandom]);
  52.             }
  53.        }
  54.         for($k=0;$k<20;$k++){ 
  55.             $colorRandom=mt_rand(0,sizeof($colorList)-1);
  56.             imagesetpixel($image,rand()%70,rand()%15,$colorList[$colorRandom]);
  57.     
  58.         }
  59.         // 添加干扰线
  60.         for($k=0;$k<3;$k++){
  61.             $colorRandom=mt_rand(0,sizeof($colorList)-1);
  62.             $todrawline=1;
  63.             if($todrawline){
  64.                 imageline($image,mt_rand(0,$width),mt_rand(0,$height),mt_rand(0,$width),mt_rand(0,$height),$colorList[$colorRandom]);
  65.             }else{
  66.                 $w=mt_rand(0,$width);
  67.                 $h=mt_rand(0,$width);
  68.                 imagearc($image,$width-floor($w / 2),floor($h / 2),$w,$h, rand(90,180),rand(180,270),$colorList[$colorRandom]);
  69.             }
  70.         }
  71.         imagegif($image);
  72.         imagedestroy($image);
  73.         $imagedata[]=ob_get_contents();
  74.         ob_clean();
  75.         ++$i;
  76.     }
  77.     $gif=new GIFEncoder($imagedata);
  78.     Header('Content-type:image/gif');
  79.     echo $gif->GetAnimation();
  80.     }
然后将GIFEncoder类文件放入同级目录中
  1. <?php
  2. /**
  3. *GIFEncoder类
  4. **/
  5. Class GIFEncoder{
  6.     var $GIF="GIF89a";              /* GIF header 6 bytes       */  
  7.     var $VER="GIFEncoder V2.06";      /* Encoder version            */  
  8.     var $BUF=Array();
  9.     var $LOP=0;
  10.     var $DIS=2;
  11.     var $COL=-1;
  12.     var $IMG=-1;
  13.     var $ERR=Array(
  14.         'ERR00'=>"Does not supported function for only one image!", 
  15.         'ERR01'=>"Source is not a GIF image!", 
  16.         'ERR02'=>"Unintelligible flag ", 
  17.         'ERR03'=>"Could not make animation from animated GIF source", 
  18.    );
  19.     function GIFEncoder($GIF_src,$GIF_dly=100,$GIF_lop=0,$GIF_dis=0, $GIF_red=0,$GIF_grn=0,$GIF_blu=0,$GIF_mod='bin'){
  20.         if(!is_array($GIF_src)&&!is_array($GIF_tim)){
  21.             printf("%s: %s",$this->VER,$this->ERR['ERR00']);
  22.             exit(0);
  23.         }  
  24.         $this->LOP=($GIF_lop>-1)?$GIF_lop:0;
  25.         $this->DIS=($GIF_dis>-1)?(($GIF_dis<3)?$GIF_dis:3):2;
  26.         $this->COL=($GIF_red>-1&&$GIF_grn>-1&&$GIF_blu>-1)?($GIF_red |($GIF_grn<<8)|($GIF_blu<<16)):-1;

  27.         for($i=0,$src_count=count($GIF_src);$i<$src_count;$i++){
  28.             if(strToLower($GIF_mod)=="url"){
  29.                 $this->BUF[]=fread(fopen($GIF_src [$i],"rb"),filesize($GIF_src [$i]));
  30.            }elseif(strToLower($GIF_mod)=="bin"){
  31.                 $this->BUF [ ]=$GIF_src [ $i ];
  32.            }else{
  33.                 printf("%s: %s(%s)!",$this->VER,$this->ERR [ 'ERR02' ],$GIF_mod);
  34.                 exit(0);
  35.            }  
  36.             if(substr($this->BUF[$i],0,6)!="GIF87a"&&substr($this->BUF [$i],0,6)!="GIF89a"){
  37.                 printf("%s: %d %s",$this->VER,$i,$this->ERR ['ERR01']);
  38.                 exit(0);
  39.            }  
  40.             for($j=(13+3*(2<<(ord($this->BUF[$i]{10})&0x07))),$k=TRUE;$k;$j++){
  41.                 switch($this->BUF [$i]{$j}){
  42.                     case "!":  
  43.                         if((substr($this->BUF[$i],($j+3),8))=="NETSCAPE"){
  44.                                 printf("%s: %s(%s source)!",$this->VER,$this->ERR ['ERR03'],($i+1));
  45.                                 exit(0);
  46.                        }  
  47.                         break;
  48.                     case ";":  
  49.                         $k=FALSE;
  50.                     break;
  51.                }  
  52.            }  
  53.         }  
  54.         GIFEncoder::GIFAddHeader();
  55.         for($i=0,$count_buf=count($this->BUF);$i<$count_buf;$i++){
  56.             GIFEncoder::GIFAddFrames($i,$GIF_dly[$i]);
  57.        }  
  58.         GIFEncoder::GIFAddFooter();
  59.     }  
  60.     function GIFAddHeader(){
  61.         $cmap=0;
  62.         if(ord($this->BUF[0]{10})&0x80){
  63.             $cmap=3*(2<<(ord($this->BUF [0]{10})&0x07));
  64.             $this->GIF.=substr($this->BUF [0],6,7);
  65.             $this->GIF.=substr($this->BUF [0],13,$cmap);
  66.             $this->GIF.="!\377\13NETSCAPE2.0\3\1".GIFEncoder::GIFWord($this->LOP)."\0";
  67.         }  
  68.     }  
  69.     function GIFAddFrames($i,$d){
  70.         $Locals_str=13+3*(2 <<(ord($this->BUF[$i]{10})&0x07));
  71.         $Locals_end=strlen($this->BUF[$i])-$Locals_str-1;
  72.         $Locals_tmp=substr($this->BUF[$i],$Locals_str,$Locals_end);
  73.         $Global_len=2<<(ord($this->BUF [0]{10})&0x07);
  74.         $Locals_len=2<<(ord($this->BUF[$i]{10})&0x07);
  75.         $Global_rgb=substr($this->BUF[0],13,3*(2<<(ord($this->BUF[0]{10})&0x07)));
  76.         $Locals_rgb=substr($this->BUF[$i],13,3*(2<<(ord($this->BUF[$i]{10})&0x07)));
  77.         $Locals_ext="!\xF9\x04".chr(($this->DIS<<2)+0).chr(($d>>0)&0xFF).chr(($d>>8)&0xFF)."\x0\x0";
  78.         if($this->COL>-1&&ord($this->BUF[$i]{10})&0x80){
  79.             for($j=0;$j<(2<<(ord($this->BUF[$i]{10})&0x07));$j++){
  80.                 if(ord($Locals_rgb{3*$j+0})==($this->COL>> 0)&0xFF&&ord($Locals_rgb{3*$j+1})==($this->COL>> 8)&0xFF&&ord($Locals_rgb{3*$j+2})==($this->COL>>16)&0xFF){
  81.                     $Locals_ext="!\xF9\x04".chr(($this->DIS<<2)+1).chr(($d>>0)&0xFF).chr(($d>>8)&0xFF).chr($j)."\x0";
  82.                     break;
  83.                }  
  84.            }  
  85.         }  
  86.         switch($Locals_tmp{0}){
  87.             case "!":  
  88.                 $Locals_img=substr($Locals_tmp,8,10);
  89.                 $Locals_tmp=substr($Locals_tmp,18,strlen($Locals_tmp)-18);
  90.                 break;
  91.             case ",":  
  92.                 $Locals_img=substr($Locals_tmp,0,10);
  93.                 $Locals_tmp=substr($Locals_tmp,10,strlen($Locals_tmp)-10);
  94.                 break;
  95.         }  
  96.         if(ord($this->BUF[$i]{10})&0x80&&$this->IMG>-1){
  97.             if($Global_len==$Locals_len){
  98.                 if(GIFEncoder::GIFBlockCompare($Global_rgb,$Locals_rgb,$Global_len)){
  99.                     $this->GIF.=($Locals_ext.$Locals_img.$Locals_tmp);
  100.                 }else{
  101.                     $byte=ord($Locals_img{9});
  102.                     $byte|=0x80;
  103.                     $byte&=0xF8;
  104.                     $byte|=(ord($this->BUF [0]{10})&0x07);
  105.                     $Locals_img{9}=chr($byte);
  106.                     $this->GIF.=($Locals_ext.$Locals_img.$Locals_rgb.$Locals_tmp);
  107.                 }  
  108.             }else{
  109.                 $byte=ord($Locals_img{9});
  110.                 $byte|=0x80;
  111.                 $byte&=0xF8;
  112.                 $byte|=(ord($this->BUF[$i]{10})&0x07);
  113.                 $Locals_img {9}=chr($byte);
  114.                 $this->GIF.=($Locals_ext.$Locals_img.$Locals_rgb.$Locals_tmp);
  115.             }  
  116.         }else{
  117.             $this->GIF.=($Locals_ext.$Locals_img.$Locals_tmp);
  118.         }  
  119.         $this->IMG=1;
  120.     }  
  121.     function GIFAddFooter(){
  122.         $this->GIF.=";";
  123.     }  
  124.     function GIFBlockCompare($GlobalBlock,$LocalBlock,$Len){
  125.         for($i=0;$i<$Len;$i++){
  126.             if($GlobalBlock{3*$i+0}!=$LocalBlock{3*$i+0}||$GlobalBlock{3*$i+1}!=$LocalBlock{3*$i+1}||$GlobalBlock{3*$i+2}!=$LocalBlock{3*$i+2}){
  127.                 return(0);
  128.            }  
  129.        }  
  130.         return(1);
  131.     }  
  132.     function GIFWord($int){
  133.        return(chr($int&0xFF).chr(($int>>8)&0xFF));
  134.     }  
  135.     function GetAnimation(){
  136.         return($this->GIF);
  137.     }  
  138. }
具体使用方法和原来基本一致,只是不要传type参数,因为默认动态必须是gif格式,另外图片宽度不能小于60。
  1.     /**
  2.      * 生成验证码
  3.      * @access public
  4.      * @return void
  5.      */    
  6.     public function verify(){
  7.         import("ORG.Util.Image");
  8.         Image::buildActiveImageVerify(4,1);
  9.     }