ThinkPHP 3.2.3实现加减乘除图片验证码


Posted in PHP onDecember 05, 2018

ThinkPHP 3.2.3 自带的验证码类位于 /ThinkPHP/Library/Think/Verify.class.php,字体文件位于 /ThinkPHP/Library/Think/Verify/

可以在 Verify.class.php 文件内进行修改,也可以单独写一个类继承自带的验证码类。如果单独写一个继承的类,可以重用父类的属性和方法,但是要注意的是父类中有一些属性和方法是私有(private)的,可以修改这些私有的属性和方法为保护(protected)的,如果不希望修改框架自带的方法的话,也可以在子类中再定义这些属性和方法。

测试的控制器位于 /Application/Home/Controller/TestVerifyController.class.php

测试的试图位于 /Application/Home/View/User/verify.html

自定义的子类位于 /Applicaion/Home/Common/VerifyProcess.class.php 

VerifyProcess.class.php:

<?php
 
namespace Home\Common;
use Think\Verify;
 
class VerifyProcess extends Verify {
 
 private $_image = NULL;  // 验证码图片实例
 private $_color = NULL;  // 验证码字体颜色
 
 public function entryProcess($id = '') {
 // 图片宽(px)
 $this->imageW || $this->imageW = $this->length*$this->fontSize*1.5 +
 $this->length*$this->fontSize/2;
 // 图片高(px)
 $this->imageH || $this->imageH = $this->fontSize * 2.5;
 // 建立一幅 $this->imageW x $this->imageH 的图像
 $this->_image = imagecreate($this->imageW, $this->imageH);
 
 // 设置背景  
 imagecolorallocate($this->_image, $this->bg[0], $this->bg[1], $this->bg[2]);
 
 // 验证码字体随机颜色
 $this->_color = imagecolorallocate($this->_image, mt_rand(1,150), 
 mt_rand(1,150), mt_rand(1,150));
 // 验证码使用随机字体
 $ttfPath = $_SERVER['DOCUMENT_ROOT'].'/ThinkPHP/Library/Think/Verify/' . 
 ($this->useZh ? 'zhttfs' : 'ttfs') . '/';
 
 if(empty($this->fontttf)){
  $dir = dir($ttfPath);
  $ttfs = array();  
  while (false !== ($file = $dir->read())) {
   if($file[0] != '.' && substr($file, -4) == '.ttf') {
    $ttfs[] = $file;
   }
  }
  $dir->close();
  $this->fontttf = $ttfs[array_rand($ttfs)];
 }
 $this->fontttf = $ttfPath . $this->fontttf;
  
 if($this->useImgBg) {
  $this->_background();
 }
  
 if ($this->useNoise) {
  // 绘杂点
  $this->_writeNoise();
 }
 if ($this->useCurve) {
  // 绘干扰线
  $this->_writeCurve();
 }
  
 // 绘验证码
 $codeNX = 0; // 验证码第N个字符的左边距
 
 // 验证码为简单运算
 $a = mt_rand(1,9);
 $b = mt_rand(1,9);
 $operate_array = array('+', '-', '*');
 $key = mt_rand(0, count($operate_array) - 1);
  
 if($operate_array[$key] == '+') { // 加法
  $code = $a.'+'.$b.'=';
  $result = intval($a + $b);
 } elseif($operate_array[$key] == '-') { // 减法
  $code = max($a,$b).'-'.min($a,$b).'=';
  $result = intval(abs($a - $b));
 } else { // 乘法
  $code = $a.'*'.$b.'=';
  $result = intval($a * $b);
 }
 
 $this->length = 4;
 
 for ($i = 0; $i<$this->length; $i++) {
  $codeNX += mt_rand($this->fontSize*1.2, $this->fontSize*1.6);
  imagettftext($this->_image, $this->fontSize, mt_rand(-40, 40), 
  $codeNX, $this->fontSize*1.6, $this->_color, $this->fontttf, $code[$i]);
 }
 
 // 保存验证码
 $key  = $this->authcode($this->seKey);
 $result  = $this->authcode($result);
 $secode  = array();
 $secode['verify_code'] = $result; // 把校验码保存到session
 $secode['verify_time'] = NOW_TIME; // 验证码创建时间
 session($key.$id, $secode);
  
 header('Cache-Control: private, max-age=0, no-store, no-cache, must-revalidate');
 header('Cache-Control: post-check=0, pre-check=0', false);  
 header('Pragma: no-cache');
 header("content-type: image/png");
 
 // 输出图像
 imagepng($this->_image);
 imagedestroy($this->_image);
 }
 
 /**
 * 画杂点
 * 往图片上写不同颜色的字母或数字
 */
 private function _writeNoise() {
  $codeSet = '2345678abcdefhijkmnpqrstuvwxyz';
  for($i = 0; $i < 10; $i++){
   //杂点颜色
   $noiseColor = imagecolorallocate($this->_image, mt_rand(150,225), 
   mt_rand(150,225), mt_rand(150,225));
   for($j = 0; $j < 5; $j++) {
    // 绘杂点
    imagestring($this->_image, 5, mt_rand(-10, $this->imageW), 
   mt_rand(-10, $this->imageH), $codeSet[mt_rand(0, 29)], $noiseColor);
   }
  }
 }
 
 /**
 * 画一条由两条连在一起构成的随机正弦函数曲线作干扰线(你可以改成更帅的曲线函数)
 *  
 *  高中的数学公式咋都忘了涅,写出来
 *  正弦型函数解析式:y=Asin(ωx+φ)+b
 *  各常数值对函数图像的影响:
 *  A:决定峰值(即纵向拉伸压缩的倍数)
 *  b:表示波形在Y轴的位置关系或纵向移动距离(上加下减)
 *  φ:决定波形与X轴位置关系或横向移动距离(左加右减)
 *  ω:决定周期(最小正周期T=2π/?ω?)
 *
 */
 private function _writeCurve() {
 $px = $py = 0;
  
 // 曲线前部分
 $A = mt_rand(1, $this->imageH/2);     // 振幅
 $b = mt_rand(-$this->imageH/4, $this->imageH/4); // Y轴方向偏移量
 $f = mt_rand(-$this->imageH/4, $this->imageH/4); // X轴方向偏移量
 $T = mt_rand($this->imageH, $this->imageW*2); // 周期
 $w = (2* M_PI)/$T;
      
 $px1 = 0; // 曲线横坐标起始位置
 $px2 = mt_rand($this->imageW/2, $this->imageW * 0.8); // 曲线横坐标结束位置
 
 for ($px=$px1; $px<=$px2; $px = $px + 1) {
  if ($w!=0) {
   $py = $A * sin($w*$px + $f)+ $b + $this->imageH/2; 
   // y = Asin(ωx+φ) + b
   $i = (int) ($this->fontSize/5);
   while ($i > 0) {
    imagesetpixel($this->_image, $px + $i , $py + $i, $this->_color); 
    // 这里(while)循环画像素点比imagettftext和imagestring用字体大小一次画出
    (不用这while循环)性能要好很多   
    $i--;
   }
  }
 }
  
 // 曲线后部分
 $A = mt_rand(1, $this->imageH/2);     // 振幅 
 $f = mt_rand(-$this->imageH/4, $this->imageH/4); // X轴方向偏移量
 $T = mt_rand($this->imageH, $this->imageW*2); // 周期
 $w = (2* M_PI)/$T;  
 $b = $py - $A * sin($w*$px + $f) - $this->imageH/2;
 $px1 = $px2;
 $px2 = $this->imageW;
 
 for ($px=$px1; $px<=$px2; $px=$px+ 1) {
  if ($w!=0) {
   $py = $A * sin($w*$px + $f)+ $b + $this->imageH/2; 
   // y = Asin(ωx+φ) + b
   $i = (int) ($this->fontSize/5);
   while ($i > 0) {  
    imagesetpixel($this->_image, $px + $i, $py + $i, $this->_color); 
    $i--;
   }
  }
 }
 }
 
 /* 加密验证码 */
 private function authcode($str){
 $key = substr(md5($this->seKey), 5, 8);
 $str = substr(md5($str), 8, 10);
 return md5($key . $str);
 } 
 
 /**
 * 绘制背景图片
 * 注:如果验证码输出图片比较大,将占用比较多的系统资源
 */
 private function _background() {
  $path = dirname(__FILE__).'/Verify/bgs/';
  $dir = dir($path);
 
  $bgs = array();  
  while (false !== ($file = $dir->read())) {
   if($file[0] != '.' && substr($file, -4) == '.jpg') {
    $bgs[] = $path . $file;
   }
  }
  $dir->close();
 
  $gb = $bgs[array_rand($bgs)];
 
  list($width, $height) = @getimagesize($gb);
  // Resample
  $bgImage = @imagecreatefromjpeg($gb);
  @imagecopyresampled($this->_image, $bgImage, 0, 0, 0, 0, $this->imageW, 
  $this->imageH, $width, $height);
  @imagedestroy($bgImage);
 } 
}

TestVerifyController.class.php:

<?php
namespace Home\Controller;
use Think\Controller;
use Home\Common\VerifyProcess;
 
class TestVerifyController extends Controller {
 
 // 界面
 public function index() {
  $this->display('User/verify');
 }
 
 // 验证
 public function check_verify() {
   
  $verify = new VerifyProcess();
 if(!$verify->check($_POST['verify'])) {
  $this->error('验证码错误');
 }
 }
 
 // 显示验证码
 public function verify() {
   $verify = new VerifyProcess();
   $verify->entryProcess();
 } 
}

verify.html:

<!DOCTYPE html>
<html lang="en">
<head>
 <meta charset="UTF-8">
 <title>Document</title>
 <script src="http://lib.sinaapp.com/js/jquery/1.9.1/jquery-1.9.1.min.js"></script>
</head>
<body>
 <form action="{:U('Home/TestVerify/check_verify','','')}" method="post">
  <table>
   <tr>
    <td>验证码:</td>
    <td><input type="text" name="verify"></td>
    <td>
     <img id="verify" src="{:U('Home/TestVerify/verify','','')}" 
     style="cursor: pointer;" alt="">
     <a id="refresh" href="javascript:void(0)" rel="external nofollow" >更换验证码</a>
    </td>
   </tr>
   <tr>
    <td colspan="2">
     <input type="submit" value="提交">
    </td>
   </tr>
  </table>
 </form>
</body>
<script>
 $(function(){
 
  $src = $("#verify").attr('src');
 
  $("#refresh").click(function(){
   change_verify();
  }); 
 
  $("#verify").click(function(){
   change_verify();
  });
 
  function change_verify() {
   $('#verify').attr('src', $src + '?' + Math.random());
  }
 });
 
</script>
</html>

效果:

ThinkPHP 3.2.3实现加减乘除图片验证码

也可以点击图片更换验证码,只需要把点击事件换到图片上就行了。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木,关注三水点靠木公众号的更多精彩内容。

PHP 相关文章推荐
模拟flock实现文件锁定
Feb 14 PHP
PHP 冒泡排序算法的实现代码
Aug 08 PHP
Base64在线编码解码实现代码 演示与下载
Jan 08 PHP
php中防止伪造跨站请求的小招式
Sep 02 PHP
php强制文件下载而非在浏览器打开的自定义函数分享
May 08 PHP
PHP实现根据设备类型自动跳转相应页面的方法
Jul 24 PHP
PHP程序员不应该忽略的3点
Oct 09 PHP
详解WordPress中用于更新和获取用户选项数据的PHP函数
Mar 08 PHP
PHP在线打包下载功能示例
Oct 15 PHP
php打开本地exe程序,js打开本地exe应用程序,并传递相关参数方法
Feb 06 PHP
PHP设计模式之单例模式原理与实现方法分析
Apr 25 PHP
PHP常量及变量区别原理详解
Aug 14 PHP
php实现算术验证码功能
Dec 05 #PHP
php使用array_chunk函数将一个数组分割成多个数组
Dec 05 #PHP
Yii支持多域名cors原理的实现
Dec 05 #PHP
php判断电子邮件是否正确方法
Dec 04 #PHP
浅谈Laravel核心解读之Console内核
Dec 02 #PHP
Laravel使用scout集成elasticsearch做全文搜索的实现方法
Nov 30 #PHP
用Laravel Sms实现laravel短信验证码的发送的实现
Nov 29 #PHP
You might like
dedecms中显示数字验证码的修改方法
2007/03/21 PHP
PHP 日期时间函数的高级应用技巧
2009/10/10 PHP
PHP 日志缩略名的创建函数代码
2010/05/26 PHP
PHP Session_Regenerate_ID函数双释放内存破坏漏洞
2011/01/27 PHP
thinkphp自定义权限管理之名称判断方法
2017/04/01 PHP
Symfony查询方法实例小结
2017/06/28 PHP
laravel5.1框架基础之Blade模板继承简单使用方法分析
2019/09/05 PHP
JavaScript For Beginners(转载)
2007/01/05 Javascript
cnblogs csdn 代码运行框实现代码
2009/11/02 Javascript
javascript按位非运算符的使用方法
2013/11/14 Javascript
Javascript连接Access数据库完整实例
2015/08/03 Javascript
AngularJS整合Springmvc、Spring、Mybatis搭建开发环境
2016/02/25 Javascript
BootStrap文件上传样式超好看【持续更新】
2016/05/10 Javascript
NodeJS搭建HTTP服务器的实现步骤
2018/10/12 NodeJs
JavaScript实现的联动菜单特效示例
2019/07/08 Javascript
微信小程序开发(三):返回上一级页面并刷新操作示例【页面栈】
2020/06/01 Javascript
关于小程序优化的一些建议(小结)
2020/12/10 Javascript
微信小程序自定义modal弹窗组件的方法详解
2020/12/20 Javascript
js面向对象封装级联下拉菜单列表的实现步骤
2021/02/08 Javascript
Python3正则匹配re.split,re.finditer及re.findall函数用法详解
2018/06/11 Python
Python线程池模块ThreadPoolExecutor用法分析
2018/12/28 Python
详解Python字符串切片
2019/05/20 Python
Python hashlib模块实例使用详解
2019/12/24 Python
关于Pytorch MaxUnpool2d中size操作方式
2020/01/03 Python
python ImageDraw类实现几何图形的绘制与文字的绘制
2020/02/26 Python
Python 如何在字符串中插入变量
2020/08/01 Python
莫斯科高科技在线商店:KremlinStore
2019/03/13 全球购物
优秀中专生推荐信
2013/11/17 职场文书
管理学专业个人求职信范文
2013/12/13 职场文书
创新型城市实施方案
2014/03/06 职场文书
2014年党员自我评价材料
2014/09/22 职场文书
2014年行政后勤工作总结
2014/12/06 职场文书
2015年清明节扫墓演讲稿
2015/03/18 职场文书
追悼词范文大全
2015/06/23 职场文书
2016年暑假家长对孩子评语
2015/12/01 职场文书
MySQL复制问题的三个参数分析
2021/04/07 MySQL