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 相关文章推荐
substr()函数中文版
Oct 09 PHP
15种PHP Encoder的比较
Apr 17 PHP
php读取mysql乱码,用set names XXX解决的原理分享
Dec 29 PHP
Youku 视频绝对地址获取的方法详解
Jun 26 PHP
curl实现站外采集的方法和技巧
Jan 31 PHP
通过curl模拟post和get方式提交的表单类
Apr 23 PHP
CI框架给视图添加动态数据
Dec 01 PHP
分享十款最出色的PHP安全开发库中文详细介绍
Mar 22 PHP
Bootstrap+PHP实现多图上传功能实例详解
Apr 08 PHP
Yii框架分页技术实例分析
Aug 30 PHP
如何解决PHP获取不到SESSION信息之一般情况
Oct 10 PHP
laravel实现图片上传预览,及编辑时可更换图片,并实时变化的例子
Nov 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
JavaScript打开word文档的实现代码(c#)
2012/04/16 Javascript
js获取或设置当前窗口url参数的小例子
2013/10/14 Javascript
javascript 寻找错误方法整理
2014/06/15 Javascript
浅析js中substring和substr的方法
2015/11/09 Javascript
jQuery 利用$.ajax 时获取原生XMLHttpRequest 对象的方法
2016/08/25 Javascript
jQuery实现ToolTip元素定位显示功能示例
2016/11/23 Javascript
JS实现求数组起始项到终止项之和的方法【基于数组扩展函数】
2017/06/13 Javascript
深入浅析JavaScript中的RegExp对象
2017/09/18 Javascript
vue实现图片滚动的示例代码(类似走马灯效果)
2018/03/03 Javascript
js经验分享 JavaScript反调试技巧
2018/03/10 Javascript
Linux Centos7.2下安装nodejs&amp;npm配置全局路径的教程
2018/05/15 NodeJs
详解angular2如何手动点击特定元素上的点击事件
2018/10/16 Javascript
IE8中jQuery.load()加载页面不显示的原因
2018/11/15 jQuery
VUE组件中的 Drawer 抽屉实现代码
2019/08/06 Javascript
JavaScript的查询机制LHS和RHS解析
2019/08/16 Javascript
jquery实现有过渡效果的tab切换
2020/07/17 jQuery
JavaScript快速调试的两个技巧
2020/11/04 Javascript
python实现系统状态监测和故障转移实例方法
2013/11/18 Python
Python网络编程中urllib2模块的用法总结
2016/07/12 Python
Djang的model创建的字段和参数详解
2019/07/27 Python
python读取图像矩阵文件并转换为向量实例
2020/06/18 Python
详细分析Python垃圾回收机制
2020/07/01 Python
python opencv实现直线检测并测出倾斜角度(附源码+注释)
2020/12/31 Python
美国折扣网站:jClub
2017/08/07 全球购物
Reebok官方旗舰店:美国知名健身品牌锐步
2019/01/07 全球购物
英国排名第一的LED灯泡网站:LED Bulbs
2019/09/03 全球购物
印度第一网上礼品店:IGP.com
2020/02/06 全球购物
工业自动化专业毕业生推荐信
2013/11/18 职场文书
电气专业推荐信范文
2013/11/18 职场文书
配件采购员岗位职责
2013/12/03 职场文书
自荐书范文
2013/12/08 职场文书
2014年客房服务员工作总结
2014/11/18 职场文书
解决golang在import自己的包报错的问题
2021/04/29 Golang
JDBC连接的六步实例代码(与mysql连接)
2021/05/12 MySQL
web前端之css水平居中代码解析
2021/05/20 HTML / CSS
nginx配置之并发频次限制
2022/04/18 Servers