ThinkPHP 3.2.3 加减乘除图片验证码

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:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
<?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:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<?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:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
<!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)" >更换验证码</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>

  

效果:

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值