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 相关文章推荐
mayfish 数据入库验证代码
Apr 30 PHP
使用CodeIgniter的类库做图片上传
Jun 12 PHP
Win2003+apache+PHP+SqlServer2008 配置生产环境
Jul 29 PHP
PHP页面实现定时跳转的方法
Oct 31 PHP
php 伪造ip以及url来路信息方法汇总
Nov 25 PHP
php实现将Session写入数据库
Jul 26 PHP
大家都应该掌握的PHP关联数组使用技巧
Dec 25 PHP
WordPress中设置Post Type自定义文章类型的实例教程
May 10 PHP
PHP入门教程之面向对象基本概念实例分析
Sep 11 PHP
PHP实现链式操作的三种方法详解
Nov 16 PHP
PHP 实现手机端APP支付宝支付功能
Jun 07 PHP
laravel框架 api自定义全局异常处理方法
Oct 11 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静态类
2006/11/25 PHP
最新的php 文件上传模型,支持多文件上传
2009/08/13 PHP
浅谈php处理后端&amp;接口访问超时的解决方法
2016/10/29 PHP
PHP htmlspecialchars() 函数实例代码及用法大全
2018/09/18 PHP
JavaScript 核心参考教程 内置对象
2009/10/13 Javascript
javascript 拖放效果实现代码
2010/01/22 Javascript
在服务端(Page.Write)调用自定义的JS方法详解
2013/08/09 Javascript
JavaScript实现简单图片滚动附源码下载
2014/06/17 Javascript
javascript实现无限级select联动菜单
2015/01/02 Javascript
JavaScript学习笔记之Cookie对象
2015/01/22 Javascript
Java File类的常用方法总结
2015/03/18 Javascript
使用JQuery实现智能表单验证功能
2016/03/08 Javascript
jQuery右下角悬浮广告实例
2016/10/17 Javascript
微信小程序实战之自定义toast(6)
2017/04/18 Javascript
在vue-cli脚手架中配置一个vue-router前端路由
2017/07/03 Javascript
js 两个日期比较相差多少天的实例
2017/10/19 Javascript
AngularJS实现的省市二级联动功能示例【可对选项实现增删】
2017/10/26 Javascript
js变量值传到php过程详解 将php解析成数据
2019/06/26 Javascript
python编程羊车门问题代码示例
2017/10/25 Python
Python3结合Dlib实现人脸识别和剪切
2018/01/24 Python
利用Python正则表达式过滤敏感词的方法
2019/01/21 Python
python 带时区的日期格式化操作
2020/10/23 Python
python打包生成so文件的实现
2020/10/30 Python
Html5页面中的返回实现的方法
2018/02/26 HTML / CSS
HTML5 图片悬停放大的实现代码示例
2019/12/04 HTML / CSS
澳大利亚珍珠首饰购物网站:Vayo Pearls
2019/03/11 全球购物
日本最大的购物网站乐天市场国际版:Rakuten Global Market(支持中文)
2020/02/03 全球购物
俄罗斯在线大型超市:ТутПросто
2021/01/08 全球购物
劳动竞赛活动方案
2014/02/20 职场文书
禁毒宣传工作方案
2014/05/23 职场文书
村安全生产责任书
2014/08/25 职场文书
党的群众路线对照检查材料
2014/09/22 职场文书
阳光体育运动标语口号
2015/12/26 职场文书
2016思想纪律作风整顿心得体会
2016/01/23 职场文书
致创业您:正能量激励人心句子(48条)
2019/08/15 职场文书
Java实现二维数组和稀疏数组之间的转换
2021/06/27 Java/Android