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 相关文章推荐
数据库查询记录php 多行多列显示
Aug 15 PHP
zend api扩展的php对象的autoload工具
Apr 18 PHP
五款常用mysql slow log分析工具的比较分析
May 22 PHP
用php制作简单分页(从数据库读取记录)的方法详解
May 04 PHP
解析php防止form重复提交的方法
Jul 01 PHP
php实现俄罗斯乘法实例
Mar 07 PHP
解决nginx不支持thinkphp中pathinfo的问题
Jul 21 PHP
yii2缓存Caching基本用法示例
Jul 18 PHP
PHP对称加密函数实现数据的加密解密
Oct 27 PHP
smarty模板数学运算示例
Dec 11 PHP
PHP基于rabbitmq操作类的生产者和消费者功能示例
Jun 16 PHP
PHP生成短网址的思路以及实现方法的详解
Mar 25 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
php curl常见错误:SSL错误、bool(false)
2011/12/28 PHP
解析php中heredoc的使用方法
2013/06/17 PHP
smarty模板引擎基础知识入门
2015/03/30 PHP
php递归调用删除数组空值元素的方法
2015/04/28 PHP
php 截取GBK文档某个位置开始的n个字符方法
2017/03/08 PHP
PHP多进程通信-消息队列使用
2019/03/08 PHP
解决laravel session失效的问题
2019/10/14 PHP
javascript中巧用“闭包”实现程序的暂停执行功能
2007/04/04 Javascript
JQuery 学习笔记 选择器之一
2009/07/23 Javascript
extjs之去除s.gif的影响
2010/12/25 Javascript
常见JS效果之图片减速度滚动实现代码
2011/12/08 Javascript
Jquery动态进行图片缩略的原理及实现
2013/08/13 Javascript
jquery弹窗插件colorbox绑定动态生成元素的方法
2014/06/20 Javascript
js面向对象之公有、私有、静态属性和方法详解
2015/04/17 Javascript
AngularJS延迟加载html template
2016/07/27 Javascript
JavaScript正则获取地址栏中参数的方法
2017/03/02 Javascript
vue绑定设置属性的多种方式(5)
2017/08/16 Javascript
AngularJS实现图片上传和预览功能的方法分析
2017/11/08 Javascript
利用layer实现表单完美验证的方法
2019/09/26 Javascript
详尽讲述用Python的Django框架测试驱动开发的教程
2015/04/22 Python
django 多对多表的创建和插入代码实现
2019/09/09 Python
python 遍历pd.Series的index和value
2019/11/26 Python
Keras 中Leaky ReLU等高级激活函数的用法
2020/07/05 Python
BOSE德国官网:尽探索之力,享音乐之极
2016/12/11 全球购物
Sephora丝芙兰泰国官方网站:国际知名化妆品购物
2017/11/15 全球购物
美国珠宝店:Helzberg Diamonds
2018/10/24 全球购物
四年的个人工作自我评价
2013/12/10 职场文书
设计顾问服务计划书
2014/05/04 职场文书
2014年入党积极分子党校培训心得体会
2014/07/08 职场文书
退学证明范本3篇
2014/10/29 职场文书
2015年元旦促销方案书
2014/12/09 职场文书
运动会通讯稿50字
2015/07/20 职场文书
创业计划书之香辣虾火锅
2019/09/23 职场文书
PHP控制循环操作的时间
2021/04/01 PHP
go语言基础 seek光标位置os包的使用
2021/05/09 Golang
《最终幻想14》6.01版本4月5日推出 追加新任务新道具
2022/04/03 其他游戏