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 求质素(素数) 的实现代码
Apr 12 PHP
采集邮箱的php代码(抓取网页中的邮箱地址)
Jul 17 PHP
如何用C语言编写PHP扩展的详解
Jun 13 PHP
windows服务器中检测PHP SSL是否开启以及开启SSL的方法
Apr 25 PHP
CI(CodeIgniter)框架介绍
Jun 09 PHP
朋友网关于QQ相关的PHP代码(研究QQ的绝佳资料)
Jan 26 PHP
WampServer搭建php环境时遇到的问题汇总
Jul 23 PHP
PHP读取文件的常见几种方法
Nov 03 PHP
php微信公众平台开发(四)回复功能开发
Dec 06 PHP
PHP 7.4中使用预加载的方法详解
Jul 08 PHP
thinkPHP5框架路由常用知识点汇总
Sep 15 PHP
解决windows上php xdebug 无法调试的问题
Feb 19 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编写和读取XML的几种方式
2013/01/12 PHP
使用PHP把HTML生成PDF文件的几个开源项目介绍
2014/11/17 PHP
jQuery中的常用事件总结
2009/12/27 Javascript
jquery1.4.2 for Visual studio 2010 模板文件
2010/07/14 Javascript
使用javascript过滤html的字符串(注释标记法)
2013/07/08 Javascript
replace()方法查找字符使用示例
2013/10/28 Javascript
浅析XMLHttpRequest的缓存问题
2013/12/13 Javascript
推荐 21 款优秀的高性能 Node.js 开发框架
2014/08/18 Javascript
JS实现定时自动关闭DIV层提示框的方法
2015/05/11 Javascript
Bootstrap导航栏各元素操作方法(表单、按钮、文本)
2015/12/28 Javascript
jQuery 自定义下拉框(DropDown)附源码下载
2016/07/22 Javascript
浅谈js的异步执行
2016/10/18 Javascript
jQuery中绑定事件bind() on() live() one()的异同
2017/02/23 Javascript
微信小程序上滑加载下拉刷新(onscrollLower)分批加载数据(二)
2017/05/11 Javascript
socket.io与pm2(cluster)集群搭配的解决方案
2017/06/02 Javascript
JavaScript设计模式之工厂模式和抽象工厂模式定义与用法分析
2018/07/26 Javascript
vue.js配合$.post从后台获取数据简单demo分享
2018/08/11 Javascript
JS/HTML5游戏常用算法之碰撞检测 包围盒检测算法详解【矩形情况】
2018/12/13 Javascript
Vue数组响应式操作及高阶函数使用代码详解
2020/08/01 Javascript
js实现轮播图效果 纯js实现图片自动切换
2020/08/09 Javascript
前端vue+elementUI如何实现记住密码功能
2020/09/20 Javascript
vue-router 按需加载 component: () =&gt; import() 报错的解决
2020/09/22 Javascript
[02:47]DOTA2英雄基础教程 野性怒吼兽王
2013/12/05 DOTA
[01:26]DOTA2荣耀之路2:iG,China
2018/05/24 DOTA
python中执行shell的两种方法总结
2017/01/10 Python
Python中多个数组行合并及列合并的方法总结
2018/04/12 Python
PythonWeb项目Django部署在Ubuntu18.04腾讯云主机上
2019/04/01 Python
python xlwt如何设置单元格的自定义背景颜色
2019/09/03 Python
Python 从attribute到property详解
2020/03/05 Python
文件上传服务器-jupyter 中python解压及压缩方式
2020/04/22 Python
初中校园广播稿
2014/02/02 职场文书
个人银行贷款担保书
2014/04/01 职场文书
汉语言文学专业求职信
2014/06/19 职场文书
机电专业毕业生求职信
2014/07/01 职场文书
学校班子个人对照检查材料思想汇报
2014/09/27 职场文书
2021年最新用于图像处理的Python库总结
2021/06/15 Python