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通过COM使用ADODB的简单例子
Dec 31 PHP
php判断字符以及字符串的包含方法属性
Aug 30 PHP
PHPMailer 中文使用说明小结
Jan 22 PHP
php set_time_limit(0) 设置程序执行时间的函数
May 26 PHP
php学习笔记之 函数声明
Jun 09 PHP
PHP中使用smarty生成静态文件的例子
Apr 24 PHP
php使用数组填充下拉列表框的方法
Mar 31 PHP
IIS 7.5 asp Session超时时间设置方法
Apr 17 PHP
PHP实现对图片的反色处理功能【测试可用】
Feb 01 PHP
PHP切割汉字的常用方法实例总结
Apr 27 PHP
Laravel 添加多语言提示信息的方法
Sep 29 PHP
关于PHP数组迭代器的使用方法实例
Nov 17 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
php中常量DIRECTORY_SEPARATOR用法深入分析
2014/11/14 PHP
php实现以只读方式打开文件的方法
2015/03/16 PHP
php mysqli查询语句返回值类型实例分析
2016/06/29 PHP
PHP设计模式之建造者模式(Builder)原理与用法案例详解
2019/12/12 PHP
javascript函数库-集合框架
2007/04/27 Javascript
简单实用的js调试logger组件实现代码
2010/11/20 Javascript
在一个js文件里远程调用jquery.js会在ie8下的一个奇怪问题
2010/11/28 Javascript
Jquery下判断Id是否存在的代码
2011/01/06 Javascript
jQuery中对未来的元素绑定事件用bind、live or on
2014/04/17 Javascript
Javascript遍历Html Table示例(包括内容和属性值)
2014/07/08 Javascript
jQuery简单实现日历的方法
2015/05/04 Javascript
JavaScript引用类型和基本类型详解
2016/01/06 Javascript
node-http-proxy修改响应结果实例代码
2016/06/06 Javascript
JavaScript实现翻页功能(附效果图)
2017/02/16 Javascript
详解angular用$sce服务来过滤HTML标签
2017/04/11 Javascript
JS如何实现在页面上快速定位(锚点跳转问题)
2017/08/14 Javascript
详解如何用模块化的方式写vuejs
2017/12/16 Javascript
VUE实现移动端列表筛选功能
2019/08/23 Javascript
详解vue 组件
2020/06/11 Javascript
js在HTML的三种引用方式详解
2020/08/29 Javascript
Python编程入门的一些基本知识
2015/05/13 Python
python中 chr unichr ord函数的实例详解
2017/08/06 Python
通过python+selenium3实现浏览器刷简书文章阅读量
2017/12/26 Python
Python将字符串常量转化为变量方法总结
2019/03/17 Python
Pycharm 2020年最新激活码(亲测有效)
2020/09/18 Python
Python函数递归调用实现原理实例解析
2020/08/11 Python
python Protobuf定义消息类型知识点讲解
2021/03/02 Python
CSS3模拟动画下拉菜单效果
2017/04/12 HTML / CSS
希腊香水和化妆品购物网站:Parfimo.gr
2019/10/03 全球购物
最新党员的自我评价分享
2013/11/04 职场文书
最新大学生创业计划书写作攻略
2014/04/02 职场文书
工厂门卫岗位职责范本
2014/04/04 职场文书
2015年办公室个人工作总结
2015/04/20 职场文书
追讨欠款律师函
2015/05/27 职场文书
如何在Mac上通过docker配置PHP开发环境
2021/05/29 PHP
pytorch中的 .view()函数的用法介绍
2022/03/17 Python