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


Posted in PHP onMarch 12, 2018

现在好多网站使用的验证码非常容易被软件自动识别到,本文介绍了一种PHP生成复杂验证码加入倾斜,弦干扰线,黏贴,旋转等效果

常见的软件不容易自动识别的验证码做法有以下3种:

1、字体变型 (一般通过算法,进行扭曲)

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

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

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

3、干扰线,噪点 (这种识别起来相当容易,很容易被程序自动化识别)

对于上面提到,第1,2 二种方法,在识别时候,是比较困难的。

具体实现代码:

<?php
/**
 *带文字旋转,倾斜,黏贴,加正弦干扰线验证码*
 */
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;
		}
	}
}

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生成复杂验证码(倾斜,正弦干扰线,黏贴,旋转)

大家可以修改代码中的相应数值达到自己需要的复杂度

PHP 相关文章推荐
php面向对象全攻略 (一) 面向对象基础知识
Sep 30 PHP
ThinkPHP3.2.2的插件控制器功能
Mar 05 PHP
php实现对两个数组进行减法操作的方法
Apr 17 PHP
PHP发送短信代码分享
Aug 11 PHP
微信公众平台开发之天气预报功能
Aug 31 PHP
PHP调试及性能分析工具Xdebug详解
Feb 09 PHP
PHP面相对象中的重载与重写
Feb 13 PHP
PHP实现向关联数组指定的Key之前插入元素的方法
Jun 06 PHP
PHPUnit测试私有属性和方法功能示例
Jun 12 PHP
CI框架教程之优化验证码机制详解【验证码辅助函数】
Apr 16 PHP
ThinkPHP框架结合Ajax实现用户名校验功能示例
Jul 03 PHP
laravel框架使用FormRequest进行表单验证,验证异常返回JSON操作示例
Feb 18 PHP
php把字符串指定字符分割成数组的方法
Mar 12 #PHP
bindParam和bindValue的区别以及在Yii2中的使用详解
Mar 12 #PHP
php取出数组单个值的方法
Mar 12 #PHP
php合并数组并保留键值的实现方法
Mar 12 #PHP
php删除二维数组中的重复值方法
Mar 12 #PHP
PHP重置数组为连续数字索引的几种方式总结
Mar 12 #PHP
php关联数组与索引数组及其显示方法
Mar 12 #PHP
You might like
详解在PHP的Yii框架中使用行为Behaviors的方法
2016/03/18 PHP
使用正则去除php代码中的注释方法
2016/11/03 PHP
PHP实现的贪婪算法实例
2017/10/17 PHP
jquery json 实例代码
2010/12/02 Javascript
一行代码实现纯数据json对象的深度克隆实现思路
2013/01/09 Javascript
JS操作数据库的实例代码
2013/10/17 Javascript
Jquery获得控件值的三种方法总结
2014/02/13 Javascript
jQuery淡入淡出元素让其效果更为生动
2014/09/01 Javascript
基于BootStrap的前端分页带省略号和上下页效果
2017/05/18 Javascript
vue生命周期实例小结
2018/08/15 Javascript
从零开始搭建vue移动端项目到上线的步骤
2018/10/15 Javascript
详解vue-router 动态路由下子页面多页共活的解决方案
2019/12/22 Javascript
javascript中可能用得到的全部的排序算法
2020/03/05 Javascript
vuex存取值和映射函数使用说明
2020/07/24 Javascript
使用js和canvas实现时钟效果
2020/09/08 Javascript
[01:10:24]DOTA2-DPC中国联赛 正赛 VG vs Aster BO3 第一场 2月28日
2021/03/11 DOTA
Python with的用法
2014/08/22 Python
Python中input和raw_input的一点区别
2014/10/21 Python
Python基础入门之seed()方法的使用
2015/05/15 Python
python3学生名片管理v2.0版
2018/11/29 Python
python paramiko利用sftp上传目录到远程的实例
2019/01/03 Python
Python 异步协程函数原理及实例详解
2019/11/13 Python
解决django后台管理界面添加中文内容乱码问题
2019/11/15 Python
解决python-docx打包之后找不到default.docx的问题
2020/02/13 Python
Python 写了个新型冠状病毒疫情传播模拟程序
2020/02/14 Python
浅谈css3中calc在less编译时被计算的解决办法
2017/12/04 HTML / CSS
利用CSS3动画实现圆圈由小变大向外扩散的效果实例
2018/09/10 HTML / CSS
前端H5 Video常见使用场景简介
2020/08/21 HTML / CSS
家乐福巴西网上超市:Carrefour巴西
2016/10/31 全球购物
军训鉴定表自我鉴定
2014/02/13 职场文书
工厂搬迁方案
2014/05/11 职场文书
销售员岗位职责
2014/06/09 职场文书
三方股东合作协议书范本
2014/09/28 职场文书
2014年镇党建工作汇报材料
2014/11/02 职场文书
心灵捕手观后感
2015/06/02 职场文书
详解Oracle数据库中自带的所有表结构(sql代码)
2021/11/20 Oracle