php 验证码(倾斜,正弦干扰线,黏贴,旋转)


Posted in PHP onJune 29, 2013

好久没有写帖子了。一直忙着新的项目。 最近,做验证码程序,一直想做一个简洁大方,自动识别比较困难的。 通过这些时候整理搜集,发现一般做法有以下几种方案:
1、字体变型 (一般通过算法,进行扭曲,比较有代表性就是:http://code.google.com/p/cool-php-captcha/

php 验证码(倾斜,正弦干扰线,黏贴,旋转)

2、字体黏贴 (这里面以qq验证码为代表了,目前网上还是很难找到,破解qq验证码的)

php 验证码(倾斜,正弦干扰线,黏贴,旋转)

3、干扰线,噪点 (这种识别起来相当容易,很容易被程序自动化识别)
对于上面提到,第1,2 二种方法,在识别时候,是比较困难的。个人比较喜欢第二种方法,感觉看起来不是很费力。而扭曲的文字,总觉得怪怪的。 哈哈,纯粹个人喜好了。
实现代码:

<?php
/**
 *带文字旋转,倾斜,黏贴,加正弦干扰线验证码*
 *@version  0.1
 *@author http://www.cnblogs.com/chengmo
 *@copyright 程默 QQ:8292669
 */
class Utils_Caption
{
 var $Width      = 60;           //图片宽
 var $Height     = 30;           //图片高
 var $Length     = 4;            //验证码位数
 var $BgColor    = "#FFFFFF";    //背景色
 var $TFonts = array("font.ttf");
 var $TFontSize=array(17,20); //字体大小范围
 var $TFontAngle=array(-20,20); //旋转角度
 var $Chars   = "0123456789";         //验证码范围(字母数字)
 var $Code    = array();              //验证码
 var $Image   = "";              //图形对象
 var $FontColors=array('#f36161','#6bc146','#5368bd');  //字体颜色,红绿蓝
 var $TPadden = 0.75;///字符间距,多少个字符
 var $Txbase = 5;///x轴两边距离
 var $Tybase =5 ;///y轴两边距离
 var $TLine =true; ///画干扰线
 public  function RandRSI() ///生成验证码
 {
  $this->TFontAngle=range($this->TFontAngle[0],$this->TFontAngle[1]);
  $this->TFontSize=range($this->TFontSize[0],$this->TFontSize[1]);
  $arr=array();
  $Chars=$this->Chars;
  $TFontAngle=$this->TFontAngle;
  $TFontSize=$this->TFontSize;
  $FontColors=$this->FontColors;
  $code="";
  $font=dirname(__FILE__)."/font/".$this->TFonts[0];
  $charlen=strlen($Chars)-1;
  $anglelen=count($TFontAngle)-1; // 角度范围
  $fontsizelen=count($TFontSize)-1; // 角度范围
  $fontcolorlen=count($FontColors)-1; // 角度范围
  for($i=0;$i<$this->Length;$i++) ///得到字符与颜色
  {
   $char=$Chars[rand(0,$charlen)]; ///得到字符
   $angle=$TFontAngle[rand(0,$anglelen)]; ///旋转角度
   $fontsize=$TFontSize[rand(0,$fontsizelen)]; ///字体大小
   $fontcolor=$FontColors[rand(0,$fontcolorlen)]; ///字体大小
   $bound=$this->_calculateTextBox($fontsize,$angle,$font,$char); ///得到范围
   $arr[]=array($fontsize,$angle,$fontcolor,$char,$font,$bound);  ///得到矩形框
   $code.=$char;
  }
  $this->Code=$arr; //验证码
  return $code;
 }
 public function Draw() ///画图
 {
  if(empty($this->Code)) $this->RandRSI();
  $codes=$this->Code; ///用户验证码
  $wh=$this->_getImageWH($codes);
  $width=$wh[0];
  $height=$wh[1]; ///高度
  $this->Width=$width;
  $this->Height=$height;
  $this->Image = imageCreate( $width, $height );
  $image=$this->Image;
  $back = $this->_getColor2($this->_getColor( $this->BgColor)); ///背景颜色
  imageFilledRectangle($image, 0, 0, $width, $height, $back); ///填充背景
  $TPadden=$this->TPadden;
  $basex=$this->Txbase;
  $color=null;
  foreach ($codes as $v) ///逐个画字符
  {
   $bound=$v[5];
   $color=$this->_getColor2($this->_getColor($v[2]));
   imagettftext($image, $v[0], $v[1], $basex, $bound['height'],$color , $v[4], $v[3]);
   $basex=$basex+$bound['width']*$TPadden-$bound['left'];///计算下一个左边距
  }
  $this->TLine?$this->_wirteSinLine($color,$basex):null; ///画干扰线
  header("Content-type: image/png");
  imagepng( $image);
  imagedestroy($image);
 }
 /**
  *通过字体角度得到字体矩形宽度*
  *
  * @param int $font_size 字体尺寸
  * @param float $font_angle 旋转角度
  * @param string $font_file 字体文件路径
  * @param string $text 写入字符
  * @return array 返回长宽高
  */
 private function _calculateTextBox($font_size, $font_angle, $font_file, $text) {
  $box = imagettfbbox($font_size, $font_angle, $font_file, $text);
  $min_x = min(array($box[0], $box[2], $box[4], $box[6]));
  $max_x = max(array($box[0], $box[2], $box[4], $box[6]));
  $min_y = min(array($box[1], $box[3], $box[5], $box[7]));
  $max_y = max(array($box[1], $box[3], $box[5], $box[7]));
  return array(
  'left' => ($min_x >= -1) ? -abs($min_x + 1) : abs($min_x + 2),
  'top' => abs($min_y),
  'width' => $max_x - $min_x,
  'height' => $max_y - $min_y,
  'box' => $box
  );
 }
 private function  _getColor( $color ) //#ffffff
 {
  return array(hexdec($color[1].$color[2]),hexdec($color[3].$color[4]),hexdec($color[5].$color[6]));
 }
 private function  _getColor2( $color ) //#ffffff
 {
  return imagecolorallocate ($this->Image, $color[0], $color[1], $color[2]);
 }
 private function _getImageWH($data)
 {
  $TPadden=$this->TPadden;
  $w=$this->Txbase;
  $h=0;
  foreach ($data as $v)
  {
   $w=$w+$v[5]['width']*$TPadden-$v[5]['left'];
   $h=$h>$v[5]['height']?$h:$v[5]['height'];
  }
  return array(max($w,$this->Width),max($h,$this->Height));
 }
 //画正弦干扰线
 private function _wirteSinLine($color,$w)
 {
  $img=$this->Image;
  $h=$this->Height;
  $h1=rand(-5,5);
  $h2=rand(-1,1);
  $w2=rand(10,15);
  $h3=rand(4,6);
  for($i=-$w/2;$i<$w/2;$i=$i+0.1)
  {
   $y=$h/$h3*sin($i/$w2)+$h/2+$h1;
   imagesetpixel($img,$i+$w/2,$y,$color);
   $h2!=0?imagesetpixel($img,$i+$w/2,$y+$h2,$color):null;
  }
 }
}

外带字体:
font.ttf ,一个简单粗体文件。
php 验证码(倾斜,正弦干扰线,黏贴,旋转)

说明:先看下运行效果吧,大家也不要忙着复制运行了。

php 验证码(倾斜,正弦干扰线,黏贴,旋转)php 验证码(倾斜,正弦干扰线,黏贴,旋转)php 验证码(倾斜,正弦干扰线,黏贴,旋转)php 验证码(倾斜,正弦干扰线,黏贴,旋转)php 验证码(倾斜,正弦干扰线,黏贴,旋转)
主要特点是:旋转,然后黏贴,干扰线是线粗细可以变,然后正弦波形可以变化。
比较复杂是:calculateTextBox 这个函数,这个是得到字符旋转后的宽度高度。
demo:

$rsi = new Utils_Caption();
$rsi->TFontSize=array(15,17);
$rsi->Width=50;
$rsi->Height=25;
$code = $rsi->RandRSI();
session_start();
$_SESSION["CHECKCODE"] = $code;
$rsi->Draw();

好了,就写这么些了,代码还有很多不足之处。
点击下载代码
PHP 相关文章推荐
php cli 方式 在crotab中运行解决
Feb 08 PHP
PHP抽象类 介绍
Jun 13 PHP
解析php时间戳与日期的转换
Jun 06 PHP
php获得网站访问统计信息类Compete API用法实例
Apr 02 PHP
Laravel+jQuery实现AJAX分页效果
Sep 14 PHP
PHP云打印类完整示例
Oct 15 PHP
CakePHP框架Model关联对象用法分析
Aug 04 PHP
利用Homestead快速运行一个Laravel项目的方法详解
Nov 14 PHP
360搜索引擎自动收录php改写方案
Apr 28 PHP
PHP添加PNG图片背景透明水印操作类定义与用法示例
Mar 12 PHP
laravel执行php artisan migrate报错的解决方法
Oct 09 PHP
PHP实现腾讯短网址生成api接口实例
Dec 08 PHP
浅谈web上存漏洞及原理分析、防范方法(文件名检测漏洞)
Jun 29 #PHP
探讨:web上存漏洞及原理分析、防范方法
Jun 29 #PHP
浅谈web上存漏洞及原理分析、防范方法(安全文件上存方法)
Jun 29 #PHP
解析web文件操作常见安全漏洞(目录、文件名检测漏洞)
Jun 29 #PHP
解析PHP中empty is_null和isset的测试
Jun 29 #PHP
浅析Dos下运行php.exe,出现没有找到php_mbstring.dll 错误的解决方法
Jun 29 #PHP
浅析PHP中的UNICODE 编码与解码
Jun 29 #PHP
You might like
电脑硬件及电脑配置知识大全
2020/03/17 数码科技
PHP中通过ADO调用Access数据库的方法测试不通过
2006/12/31 PHP
IP138 IP地址查询小偷实现代码
2010/02/15 PHP
PHP中把错误日志保存在系统日志中(Windows系统)
2015/06/23 PHP
会自动逐行上升的文本框
2006/06/30 Javascript
“不能执行已释放的Script代码”错误的原因及解决办法
2007/09/09 Javascript
javascript 面向对象编程  function是方法(函数)
2009/09/17 Javascript
Extjs TriggerField在弹出窗口显示不出问题的解决方法
2010/01/08 Javascript
实例讲解JS中数组Array的操作方法
2014/05/09 Javascript
Ext GridPanel加载完数据后进行操作示例代码
2014/06/17 Javascript
Javascript中的高阶函数介绍
2015/03/15 Javascript
js实现类似新浪微博首页内容渐显效果的方法
2015/04/10 Javascript
jQuery检查事件是否触发的方法
2015/06/26 Javascript
javascript实现超炫的向上滑行菜单实例
2015/08/03 Javascript
JavaScript设置、获取、清除单值和多值cookie的方法
2015/11/17 Javascript
推荐三款日期选择插件(My97DatePicker、jquery.datepicker、Mobiscroll)
2017/04/21 jQuery
使用vscode快速建立vue模板过程详解
2019/10/10 Javascript
Vue插件之滑动验证码用法详解
2020/04/05 Javascript
利用Vue的v-for和v-bind实现列表颜色切换
2020/07/17 Javascript
python实现的希尔排序算法实例
2015/07/01 Python
Python画柱状统计图操作示例【基于matplotlib库】
2018/07/04 Python
Python列表元素常见操作简单示例
2019/10/25 Python
Python 生成一个从0到n个数字的列表4种方法小结
2019/11/28 Python
NumPy统计函数的实现方法
2020/01/21 Python
Python集合操作方法详解
2020/02/09 Python
python使用for...else跳出双层嵌套循环的方法实例
2020/05/17 Python
Python如何使用正则表达式爬取京东商品信息
2020/06/01 Python
Python 连接 MySQL 的几种方法
2020/09/09 Python
Canvas 文本填充线性渐变的使用详解
2020/06/22 HTML / CSS
英国50岁以上人群的交友网站:Ourtime
2018/03/28 全球购物
体育教育专业毕业生自荐信
2013/11/15 职场文书
光盘行动倡议书
2014/02/02 职场文书
社会学专业学生职业规划书
2014/02/07 职场文书
一篇文章带你复习java知识点
2021/06/28 Java/Android
Docker下安装Oracle19c
2022/04/13 Servers
Python实现数据的序列化操作详解
2022/07/07 Python