php之中文验证码

最近公司提出需要做一个中文验证码功能,并且这些中都是后台添加的,如图所示:

需要验证的就是红色的字,并且输入这一个红字就能完成验证。

另外说下我们公司的网站结构,多个子网站共用一个留言接口,验证就不能放在各个网站上面,只能以各个网站的域名加上当时生成验证码的时间为准。

 

验证码生成端class

<?php
/**
 * 
 * @author zhangshaofei@qudao.com
 * 
 * 生成验证码
 * **/
require_once("./include/config.php");//引入数据库链接文件,这个就不贴出来了,下面的mysql_query_s的方法就是这里面的,
class VerificationCode{
        
        //定义词汇
        private $_words = Array();

        
        //定义验证码的有效时间
        private $_time = '300000';
        
        //存放词汇的地址
        private $_file = './font/verification_word';
        //存放验证码的目录
        private $_code_file = './captcha/';
        
        function __construct(){
            //站点名称,标识  例如:www.ba'id'u.com
            // session_set_cookie_params($this->_time);
            // if(!isset($_SESSION)){ session_start(); }
            
            //获取词库
            $this->_words = $this->_read_word();
            
            
    }
    //读取词汇库
    public function _read_word(){
        $content = file_get_contents($this->_file);
        
        if(!$content){
            exit('Error:no words!');
        }
        return unserialize($content);
    }
    /**
         * 
         * 产生随机验证码
         * **/
        function createRandomStr($config){
            $key = array_rand($this->_words,1);
            
            $string = $this->_words[$key]['word'];
            
            
            $rand_code = $this->createImgCode($string,$config);
            
            return $rand_code;
        }
        /**
         * 验证码写入数据库
         * 
         * **/
        function set_seesion_by_name($rand_code,$config){
            if( empty($config['url']) || !isset($config['url']) ){
                exit('Error:no sitename!');
            }
            //转换网站名称
            $sitename = str_replace(".", '',  $config['url']);
            $rand_code = iconv('utf-8','gbk',$rand_code);
            $time = time();
            $s = "select * from verification_check_word  where  sitename = '".$sitename."'";   

            $res = mysql_query_s($s);
            $rs = mysql_fetch_array($res);
            if(!empty($rs))//存在则更新
            {
                $o_id = $rs['id'];
                $sql = "update verification_check_word  set word ='".$rand_code."',sitename='".$sitename."' where id='".$o_id."'";
            }else{
                $sql = "insert into verification_check_word (sitename,word,time) values ('".$sitename."','".$rand_code."','".$time."')";
            }
            
            mysql_query_s($sql);
            return $sitename;
            
        }
        /**
         * $text 为写入的词汇
         * **/
        function createImgCode($text,$config){
            header("content-Type:text/html; charset=utf-8");
            $lenth = $this->abslength($text);
            $num = $this->_rand_three_($text,$lenth);
            
            
            $start = $this->csubstr($text,0, ($num-1) );
            $center = $this->csubstr($text, ($num-1) , 1);
            $end = $this->csubstr($text, $num , ($lenth-$num));
            
            $sitename = $this->set_seesion_by_name($center,$config);//设置seesion
            
            
            
            //创建图片
            $im = imagecreate($x=135,$y=35 );
            $bg = imagecolorallocate($im,225,236,255); //第一次对 imagecolorallocate() 的调用会给基于调色板的图像填充背景色
            $fontColor = imageColorAllocate ( $im, 0, 0, 0 );   //字体颜色
               
            //最亮字
            $on = imageColorAllocate ( $im, 255, 0, 0 );   //字体颜色
            $fontstyle = './font/SIMHEI.TTF';                   //字体样式,这个可以从c:\windows\Fonts\文件夹下找到,我把它放到和authcode.php文件同一个目录,这里可以替换其他的字体样式
            
            //倾斜角度
            $jiao = rand(0,10)-rand(0,15);//rand(0,5)-rand(0,5)
            //距离顶部
            $top = 30;//rand(10,50)-rand(10,35)
            //距离
            $left = 15;
            
            imagettftext($im,20,$jiao,$left,$top,$fontColor,$fontstyle,$start);
            imagettftext($im,20,$jiao,$left+($num-1)*25+5,$top,$on,$fontstyle,$center);
            imagettftext($im,20,$jiao,$left+$num*25,$top,$fontColor,$fontstyle,$end);
            
            
            
            //干扰线
            for ($i=0;$i<8;$i++){
                    $lineColor        = imagecolorallocate($im,rand(0,255),rand(0,255),rand(0,255));
                    imageline ($im,rand(0,$x),0,rand(0,$x),$y,$lineColor);
            }
            //干扰点
            for ($i=0;$i<250;$i++){
                    imagesetpixel($im,rand(0,$x),rand(0,$y),$fontColor);
            }
            
            imagegif($im,$this->_code_file.$sitename.'.gif');
            
            return $this->_code_file.$sitename.'.gif';
            //imagedestroy($im);
            
        }
        /**
         * 生成随机数字
         * 
         * **/
        function _rand_three_($text,$lenth){
            
            $num = rand(1,$lenth);
            
            return $num;
            
            
            
        }
        /**
        * 可以统计中文字符串长度的函数
        * @param $str 要计算长度的字符串
        * @param $type 计算长度类型,0(默认)表示一个中文算一个字符,1表示一个中文算两个字符
        *
        */
        function abslength($str)
        {
            if(empty($str)){
                return 0;
            }
            if(function_exists('mb_strlen')){
                return mb_strlen($str,'utf-8');
            }
            else {
                preg_match_all("/./u", $str, $ar);
                return count($ar[0]);
            }
        }
        
        /* 
 
        * 中文截取,支持gb2312,gbk,utf-8,big5 

        * 

        * @param string $str 要截取的字串 

        * @param int $start 截取起始位置 

        * @param int $length 截取长度 

        * @param string $charset utf-8|gb2312|gbk|big5 编码 

        * @param $suffix 是否加尾缀 

        */

        public function csubstr($str, $start=0, $length, $charset="utf-8", $suffix=true) 

        { 

           if(function_exists("mb_substr")) 

           { 

               if(mb_strlen($str, $charset) <= $length) return $str; 

               $slice = mb_substr($str, $start, $length, $charset); 

           } 

           else

           { 

               $re['utf-8']   = "/[\x01-\x7f]|[\xc2-\xdf][\x80-\xbf]|[\xe0-\xef][\x80-\xbf]{2}|[\xf0-\xff][\x80-\xbf]{3}/"; 

               $re['gb2312'] = "/[\x01-\x7f]|[\xb0-\xf7][\xa0-\xfe]/"; 

               $re['gbk']          = "/[\x01-\x7f]|[\x81-\xfe][\x40-\xfe]/"; 

               $re['big5']          = "/[\x01-\x7f]|[\x81-\xfe]([\x40-\x7e]|\xa1-\xfe])/"; 

               preg_match_all($re[$charset], $str, $match); 

               if(count($match[0]) <= $length) return $str; 

               $slice = join("",array_slice($match[0], $start, $length)); 

           } 

           if($suffix) return $slice; 

           return $slice; 

        }





}


?>

下面是生成验证码

<?php
require_once("./class/VerificationCode.class.php");
$sitename = urldecode(trim($_GET['s']));
$time= trim($_GET['t']);
$gid= trim($_GET['gid']);

$config = array(
    'url' => $sitename.$time.$gid
);

$verificationCode = new VerificationCode();
$src = $verificationCode->createRandomStr($config);
//echo '<img src="http://gb.1958.cn/'.substr($src,1).'" onclick="changeImg();" id="code">';
$img_url = "http://gb.xxxx.cn".substr($src,1);
$data =array(
    'img_url'=>$img_url
);
//echo "success_jsonpCallback('$img_url')";
$callback = isset($_GET["callback"])?$_GET["callback"]:"callback";
echo $callback . "(". json_encode($data). ")"; 

//echo "callback"."(".$img_url.")";
?>

因为是跨域访问,所以我这边是json

 

 

验证码端

<?php

$time= time();
$sitename=urlencode($_SERVER['SERVER_NAME']);


?>
<div class="ly-input"> <label for="textfield">验证码:</label> <input type="text" name="code" /><img src="" onclick="changeImg();" id="code"/> </div> <script> $(function(){ changeImg(); }) function changeImg(){ $.ajax({ url : 'http://gb.xxxxx.cn/verification.php?s=<?php echo $sitename?>&t=<?php echo $time?>&gid=<?php echo $gid?>', type : 'GET', cache : false, dataType : 'jsonp', jsonp: 'callback', //默认callback success : function(data){ if(data){ $('#code').attr('src',data.img_url+'?rand='+Math.random()); } } }); } </script>

 

 

 

代码粘贴完毕

 

创建的思路是:

1、读取词汇库(我这里的词汇库就是从数据库中查询出的数组)

2、随机出一个词汇

3、从这个词汇中再随机出一个字作为验证部分,也是红色字

4、把这个红色字写入数据库,以用作留言的时候验证(其实大部分都是直接写入seesion中,因为我们公司的是好多站共用一个接口,所以session不能及时清理掉,数据的冗余),这个数据库可以定时清理,当然不清理也没有事。

5、创建一个验证码图片,并把图片地址返回。

   这步需要注意的地方:我第一次是直接用php创建动态图片的,当用到imagegif  最后输出的时候,发现  会重复两次随机(也就是第2步),会出现两次,楼主花了一上午没找到原因,就只有把图片生成了。有知道原因的大神们,请麻烦告诉我!小弟感激不尽!

6、就是查询和比对验证码了

 

 

注:大神绕过,菜鸟学习!

posted @ 2015-07-08 15:06  jack_final  阅读(245)  评论(0)    收藏  举报