PHP 验证码封装类

裴卓君
2023-12-01

    在国外网站上看到的一个很好用的验证码封装类,跟大家分享一下。

还有部分文件没有放上去。

  1 <?php
  2 /**
  3  * Script para la generaci CAPTCHAS
  4  *
  5  * @author  Jose Rodriguez <jose.rodriguez@exec.cl>
  6  * @license GPLv3
  7  * @link    http://code.google.com/p/cool-php-captcha
  8  * @package captcha
  9  * @version 0.3
 10  *
 11  */
 12 
 13 session_start();
 14 
 15 $captcha = new SimpleCaptcha();
 16 
 17 // OPTIONAL Change configuration...
 18 //$captcha->wordsFile = 'words/es.php';
 19 //$captcha->session_var = 'secretword';
 20 //$captcha->imageFormat = 'png';
 21 //$captcha->lineWidth = 3;
 22 //$captcha->scale = 3; $captcha->blur = true;
 23 //$captcha->resourcesPath = "/var/cool-php-captcha/resources";
 24 
 25 // OPTIONAL Simple autodetect language example
 26 /*
 27 if (!empty($_SERVER['HTTP_ACCEPT_LANGUAGE'])) {
 28     $langs = array('en', 'es');
 29     $lang  = substr($_SERVER['HTTP_ACCEPT_LANGUAGE'], 0, 2);
 30     if (in_array($lang, $langs)) {
 31         $captcha->wordsFile = "words/$lang.php";
 32     }
 33 }
 34 */
 35 
 36 // Image generation
 37 $captcha->CreateImage();
 38 
 39 
 40 /**
 41  * SimpleCaptcha class
 42  *
 43  */
 44 class SimpleCaptcha {
 45 
 46     /** Width of the image */
 47     public $width  = 200;
 48 
 49     /** Height of the image */
 50     public $height = 70;
 51 
 52     /** Dictionary word file (empty for random text) */
 53     public $wordsFile = 'words/en.php';
 54 
 55     /**
 56      * Path for resource files (fonts, words, etc.)
 57      *
 58      * "resources" by default. For security reasons, is better move this
 59      * directory to another location outise the web server
 60      *
 61      */
 62     public $resourcesPath = 'resources';
 63 
 64     /** Min word length (for non-dictionary random text generation) */
 65     public $minWordLength = 5;
 66 
 67     /**
 68      * Max word length (for non-dictionary random text generation)
 69      * 
 70      * Used for dictionary words indicating the word-length
 71      * for font-size modification purposes
 72      */
 73     public $maxWordLength = 8;
 74 
 75     /** Sessionname to store the original text */
 76     public $session_var = 'captcha';
 77 
 78     /** Background color in RGB-array */
 79     public $backgroundColor = array(255, 255, 255);
 80 
 81     /** Foreground colors in RGB-array */
 82     public $colors = array(
 83         array(27,78,181), // blue
 84         array(22,163,35), // green
 85         array(214,36,7),  // red
 86     );
 87 
 88     /** Shadow color in RGB-array or null */
 89     public $shadowColor = null; //array(0, 0, 0);
 90 
 91     /** Horizontal line through the text */
 92     public $lineWidth = 0;
 93 
 94     /**
 95      * Font configuration
 96      *
 97      * - font: TTF file
 98      * - spacing: relative pixel space between character
 99      * - minSize: min font size
100      * - maxSize: max font size
101      */
102     public $fonts = array(
103         'Antykwa'  => array('spacing' => -3, 'minSize' => 27, 'maxSize' => 30, 'font' => 'AntykwaBold.ttf'),
104         'Candice'  => array('spacing' =>-1.5,'minSize' => 28, 'maxSize' => 31, 'font' => 'Candice.ttf'),
105         'DingDong' => array('spacing' => -2, 'minSize' => 24, 'maxSize' => 30, 'font' => 'Ding-DongDaddyO.ttf'),
106         'Duality'  => array('spacing' => -2, 'minSize' => 30, 'maxSize' => 38, 'font' => 'Duality.ttf'),
107         'Heineken' => array('spacing' => -2, 'minSize' => 24, 'maxSize' => 34, 'font' => 'Heineken.ttf'),
108         'Jura'     => array('spacing' => -2, 'minSize' => 28, 'maxSize' => 32, 'font' => 'Jura.ttf'),
109         'StayPuft' => array('spacing' =>-1.5,'minSize' => 28, 'maxSize' => 32, 'font' => 'StayPuft.ttf'),
110         'Times'    => array('spacing' => -2, 'minSize' => 28, 'maxSize' => 34, 'font' => 'TimesNewRomanBold.ttf'),
111         'VeraSans' => array('spacing' => -1, 'minSize' => 20, 'maxSize' => 28, 'font' => 'VeraSansBold.ttf'),
112     );
113 
114     /** Wave configuracion in X and Y axes */
115     public $Yperiod    = 12;
116     public $Yamplitude = 14;
117     public $Xperiod    = 11;
118     public $Xamplitude = 5;
119 
120     /** letter rotation clockwise */
121     public $maxRotation = 8;
122 
123     /**
124      * Internal image size factor (for better image quality)
125      * 1: low, 2: medium, 3: high
126      */
127     public $scale = 2;
128 
129     /** 
130      * Blur effect for better image quality (but slower image processing).
131      * Better image results with scale=3
132      */
133     public $blur = false;
134 
135     /** Debug? */
136     public $debug = false;
137     
138     /** Image format: jpeg or png */
139     public $imageFormat = 'jpeg';
140 
141 
142     /** GD image */
143     public $im;
144 
145     public function __construct($config = array()) {
146     }
147 
148     public function CreateImage() {
149         $ini = microtime(true);
150 
151         /** Initialization */
152         $this->ImageAllocate();
153         
154         /** Text insertion */
155         $text = $this->GetCaptchaText();
156         $fontcfg  = $this->fonts[array_rand($this->fonts)];
157         $this->WriteText($text, $fontcfg);
158 
159         $_SESSION[$this->session_var] = $text;
160 
161         /** Transformations */
162         if (!empty($this->lineWidth)) {
163             $this->WriteLine();
164         }
165         $this->WaveImage();
166         if ($this->blur && function_exists('imagefilter')) {
167             imagefilter($this->im, IMG_FILTER_GAUSSIAN_BLUR);
168         }
169         $this->ReduceImage();
170 
171 
172         if ($this->debug) {
173             imagestring($this->im, 1, 1, $this->height-8,
174                 "$text {$fontcfg['font']} ".round((microtime(true)-$ini)*1000)."ms",
175                 $this->GdFgColor
176             );
177         }
178 
179 
180         /** Output */
181         $this->WriteImage();
182         $this->Cleanup();
183     }
184 
185 
186     /**
187      * Creates the image resources
188      */
189     protected function ImageAllocate() {
190         // Cleanup
191         if (!empty($this->im)) {
192             imagedestroy($this->im);
193         }
194 
195         $this->im = imagecreatetruecolor($this->width*$this->scale, $this->height*$this->scale);
196 
197         // Background color
198         $this->GdBgColor = imagecolorallocate($this->im,
199             $this->backgroundColor[0],
200             $this->backgroundColor[1],
201             $this->backgroundColor[2]
202         );
203         imagefilledrectangle($this->im, 0, 0, $this->width*$this->scale, $this->height*$this->scale, $this->GdBgColor);
204 
205         // Foreground color
206         $color           = $this->colors[mt_rand(0, sizeof($this->colors)-1)];
207         $this->GdFgColor = imagecolorallocate($this->im, $color[0], $color[1], $color[2]);
208 
209         // Shadow color
210         if (!empty($this->shadowColor) && is_array($this->shadowColor) && sizeof($this->shadowColor) >= 3) {
211             $this->GdShadowColor = imagecolorallocate($this->im,
212                 $this->shadowColor[0],
213                 $this->shadowColor[1],
214                 $this->shadowColor[2]
215             );
216         }
217     }
218 
219 
220     /**
221      * Text generation
222      *
223      * @return string Text
224      */
225     protected function GetCaptchaText() {
226         $text = $this->GetDictionaryCaptchaText();
227         if (!$text) {
228             $text = $this->GetRandomCaptchaText();
229         }
230         return $text;
231     }
232 
233 
234     /**
235      * Random text generation
236      *
237      * @return string Text
238      */
239     protected function GetRandomCaptchaText($length = null) {
240         if (empty($length)) {
241             $length = rand($this->minWordLength, $this->maxWordLength);
242         }
243 
244         $words  = "abcdefghijlmnopqrstvwyz";
245         $vocals = "aeiou";
246 
247         $text  = "";
248         $vocal = rand(0, 1);
249         for ($i=0; $i<$length; $i++) {
250             if ($vocal) {
251                 $text .= substr($vocals, mt_rand(0, 4), 1);
252             } else {
253                 $text .= substr($words, mt_rand(0, 22), 1);
254             }
255             $vocal = !$vocal;
256         }
257         return $text;
258     }
259 
260 
261     /**
262      * Random dictionary word generation
263      *
264      * @param boolean $extended Add extended "fake" words
265      * @return string Word
266      */
267     function GetDictionaryCaptchaText($extended = false) {
268         if (empty($this->wordsFile)) {
269             return false;
270         }
271 
272         // Full path of words file
273         if (substr($this->wordsFile, 0, 1) == '/') {
274             $wordsfile = $this->wordsFile;
275         } else {
276             $wordsfile = $this->resourcesPath.'/'.$this->wordsFile;
277         }
278 
279         if (!file_exists($wordsfile)) {
280             return false;
281         }
282 
283         $fp     = fopen($wordsfile, "r");
284         $length = strlen(fgets($fp));
285         if (!$length) {
286             return false;
287         }
288         $line   = rand(1, (filesize($wordsfile)/$length)-2);
289         if (fseek($fp, $length*$line) == -1) {
290             return false;
291         }
292         $text = trim(fgets($fp));
293         fclose($fp);
294 
295 
296         /** Change ramdom volcals */
297         if ($extended) {
298             $text   = preg_split('//', $text, -1, PREG_SPLIT_NO_EMPTY);
299             $vocals = array('a', 'e', 'i', 'o', 'u');
300             foreach ($text as $i => $char) {
301                 if (mt_rand(0, 1) && in_array($char, $vocals)) {
302                     $text[$i] = $vocals[mt_rand(0, 4)];
303                 }
304             }
305             $text = implode('', $text);
306         }
307 
308         return $text;
309     }
310 
311 
312     /**
313      * Horizontal line insertion
314      */
315     protected function WriteLine() {
316 
317         $x1 = $this->width*$this->scale*.15;
318         $x2 = $this->textFinalX;
319         $y1 = rand($this->height*$this->scale*.40, $this->height*$this->scale*.65);
320         $y2 = rand($this->height*$this->scale*.40, $this->height*$this->scale*.65);
321         $width = $this->lineWidth/2*$this->scale;
322 
323         for ($i = $width*-1; $i <= $width; $i++) {
324             imageline($this->im, $x1, $y1+$i, $x2, $y2+$i, $this->GdFgColor);
325         }
326     }
327 
328     /**
329      * Text insertion
330      */
331     protected function WriteText($text, $fontcfg = array()) {
332         if (empty($fontcfg)) {
333             // Select the font configuration
334             $fontcfg  = $this->fonts[array_rand($this->fonts)];
335         }
336 
337         // Full path of font file
338         $fontfile = $this->resourcesPath.'/fonts/'.$fontcfg['font'];
339 
340 
341         /** Increase font-size for shortest words: 9% for each glyp missing */
342         $lettersMissing = $this->maxWordLength-strlen($text);
343         $fontSizefactor = 1+($lettersMissing*0.09);
344 
345         // Text generation (char by char)
346         $x      = 20*$this->scale;
347         $y      = round(($this->height*27/40)*$this->scale);
348         $length = strlen($text);
349         for ($i=0; $i<$length; $i++) {
350             $degree   = rand($this->maxRotation*-1, $this->maxRotation);
351             $fontsize = rand($fontcfg['minSize'], $fontcfg['maxSize'])*$this->scale*$fontSizefactor;
352             $letter   = substr($text, $i, 1);
353 
354             if ($this->shadowColor) {
355                 $coords = imagettftext($this->im, $fontsize, $degree,
356                     $x+$this->scale, $y+$this->scale,
357                     $this->GdShadowColor, $fontfile, $letter);
358             }
359             $coords = imagettftext($this->im, $fontsize, $degree,
360                 $x, $y,
361                 $this->GdFgColor, $fontfile, $letter);
362             $x += ($coords[2]-$x) + ($fontcfg['spacing']*$this->scale);
363         }
364 
365         $this->textFinalX = $x;
366     }
367 
368     /**
369      * Wave filter
370      */
371     protected function WaveImage() {
372         // X-axis wave generation
373         $xp = $this->scale*$this->Xperiod*rand(1,3);
374         $k = rand(0, 100);
375         for ($i = 0; $i < ($this->width*$this->scale); $i++) {
376             imagecopy($this->im, $this->im,
377                 $i-1, sin($k+$i/$xp) * ($this->scale*$this->Xamplitude),
378                 $i, 0, 1, $this->height*$this->scale);
379         }
380 
381         // Y-axis wave generation
382         $k = rand(0, 100);
383         $yp = $this->scale*$this->Yperiod*rand(1,2);
384         for ($i = 0; $i < ($this->height*$this->scale); $i++) {
385             imagecopy($this->im, $this->im,
386                 sin($k+$i/$yp) * ($this->scale*$this->Yamplitude), $i-1,
387                 0, $i, $this->width*$this->scale, 1);
388         }
389     }
390 
391     /**
392      * Reduce the image to the final size
393      */
394     protected function ReduceImage() {
395         
396         $imResampled = imagecreatetruecolor($this->width, $this->height);
397         imagecopyresampled($imResampled, $this->im,
398             0, 0, 0, 0,
399             $this->width, $this->height,
400             $this->width*$this->scale, $this->height*$this->scale
401         );
402         imagedestroy($this->im);
403         $this->im = $imResampled;
404     }
405 
406 
407     /**
408      * File generation
409      */
410     protected function WriteImage() {
411         if ($this->imageFormat == 'png' && function_exists('imagepng')) {
412             header("Content-type: image/png");
413             imagepng($this->im);
414         } else {
415             header("Content-type: image/jpeg");
416             imagejpeg($this->im, null, 80);
417         }
418     }
419 
420     /**
421      * Cleanup
422      */
423     protected function Cleanup() {
424         imagedestroy($this->im);
425     }
426 }
427 
428 ?>

 

转载于:https://www.cnblogs.com/jackyxie/archive/2013/01/09/2853800.html

 类似资料: