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基础知识:类与对象(2) 自动加载对象
Dec 13 PHP
PHP Smarty生成EXCEL文档的代码
Aug 23 PHP
比较discuz和ecshop的截取字符串函数php版
Sep 03 PHP
浅析is_writable的php实现
Jun 18 PHP
163的邮件用phpmailer发送(实例详解)
Jun 24 PHP
php 批量生成html,txt文件的实现代码
Jun 26 PHP
PHP获取服务器端信息的方法
Nov 28 PHP
php使用递归函数实现数字累加的方法
Mar 16 PHP
PHP实现清除wordpress里恶意代码
Oct 21 PHP
PHP 获取指定地区的天气实例代码
Feb 08 PHP
PHP获取MySQL执行sql语句的查询时间方法
Aug 21 PHP
ThinkPHP5.1框架数据库链接和增删改查操作示例
Aug 03 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
使用MaxMind 根据IP地址对访问者定位
2006/10/09 PHP
PHP中Session的概念
2006/10/09 PHP
php在多维数组中根据键名快速查询其父键以及父键值的代码
2011/05/07 PHP
PHP使用 Imagick 扩展实现图片合成,圆角处理功能示例
2019/09/09 PHP
PHP多进程简单实例小结
2019/11/09 PHP
php 下 html5 XHR2 + FormData + File API 上传文件操作实例分析
2020/02/28 PHP
javascript中的array数组使用技巧
2010/01/31 Javascript
js判断是否为数组的函数: isArray()
2011/10/30 Javascript
jquery.bgiframe.js在IE9下提示INVALID_CHARACTER_ERR错误
2013/01/11 Javascript
js中的cookie的读写操作示例详解
2014/04/17 Javascript
TypeScript 中接口详解
2015/06/19 Javascript
再谈JavaScript线程
2015/07/10 Javascript
js实现人才网站职位选择功能的方法
2015/08/14 Javascript
JS 设置Cookie 有效期 检测cookie
2017/06/15 Javascript
QRCode.js:基于JQuery的生成二维码JS库的使用
2017/06/23 jQuery
基于zepto.js实现手机相册功能
2017/07/11 Javascript
详解如何用webpack打包一个网站应用项目
2017/07/12 Javascript
原生JS实现小小的音乐播放器
2017/10/16 Javascript
使用Bootrap和Vue实现仿百度搜索功能
2017/10/26 Javascript
微信小程序实现菜单左右联动
2020/05/19 Javascript
vue 解决setTimeOut和setInterval函数无效报错的问题
2020/07/30 Javascript
解决vue watch数据的方法被调用了两次的问题
2020/11/07 Javascript
JavaScript实现音乐导航效果
2020/11/19 Javascript
[39:07]LGD vs VP 2018国际邀请赛淘汰赛BO3 第二场 8.21
2018/08/22 DOTA
python opencv实现切变换 不裁减图片
2018/07/26 Python
浅述python中深浅拷贝原理
2018/09/18 Python
Python爬虫:url中带字典列表参数的编码转换方法
2019/08/21 Python
深入浅析python的第三方库pandas
2020/02/13 Python
PyQt5通过信号实现MVC的示例
2021/02/06 Python
有原因的手表:Flex Watches
2019/03/23 全球购物
初二物理教学反思
2014/01/29 职场文书
工商企业管理专业自荐信范文
2014/04/12 职场文书
环境保护与污染治理求职信
2014/07/16 职场文书
学习张林森心得体会
2014/09/10 职场文书
党员干部作风建设思想汇报范文
2014/10/25 职场文书
教你使用Ubuntu搭建DNS服务器
2022/09/23 Servers