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、就是查询和比对验证码了
注:大神绕过,菜鸟学习!

浙公网安备 33010602011771号