正如標題所說那樣,本文只討論輸出內容所有爲中文或者包含中文的狀況。若是內容全是字母或者其餘字符的話,能夠參考這篇博客:生成驗證碼php
此處要注意,標題中爲何要區別windows和linux分別實現?由於我在網上搜了不少的博客,幾乎全部的博客都是同樣的,全是使用的windows系統,源代碼在linux上跑不通,會提示一個函數imagettftext()不存在,這個函數在windows下是可使用的,可是在linux上面確實不行的。這是爲何呢?html
有人說是linux的gd庫版本過低了,應該升級爲高版本的gd庫????linux
且不說是否是真麼gd庫太老了,另一個問題就是,使用imagettftext()函數的時候,須要傳遞一個參數,參數就是字體的文件的路徑及名稱。這個該怎麼整?canvas
因此下面就按照上面的問題來敘述。windows
先看下面這個phpinfo()中對gd庫的描述:安全
再看下面一個系統中phpinfo()的輸出:session
仔細注意上面兩個gd庫的區別,就會發現,第二個gd庫相對於第一個gd庫要多一些「功能」,這個功能就是關係到能不能使用imagettftext()函數。app
在一些linux上使用imagettftext()函數時,會提示函數不存在,可是,在windows上就行,其實就是這個緣由。dom
若是你的php上面沒有這個FreeType,能夠在網上找一下相關的博客。函數
多字節字符串的截斷、求長度的問題,可使用mb_擴展,不然會出現亂碼。
中文驗證碼的內容是中文,因此,要使用中文的字體,能夠上網下載便可。在imagettftext()指定字體文件的路徑以及文件名和擴展名便可。
產生的驗證碼內容存儲在session中(在captcha.php完成),提交驗證碼(在index.php中完成)以後,在validate.php中將提交的驗證碼和session中的驗證碼做對比便可。
若是要安全一點的話,能夠將驗證碼加密後再存session。
<?php class Captcha{ private $width;//驗證碼的寬 private $height;//驗證碼的高 private $num;//驗證碼字符的個數 private $code;//驗證碼的字符串 private $img;//驗證碼source //初始化 function __construct($width=80,$height=20,$num=4){ mb_internal_encoding("UTF-8"); $this->width=$width; $this->height=$height; $this->num=$num; $this->code=$this->create_code(); } //建立畫布 private function create_canvas(){ $this->img=imagecreatetruecolor($this->width,$this->height); $background_color=imagecolorallocate($this->img,0xFF,0xFF,0xFF); imagefill($this->img,0,0,$background_color); $border_color=imagecolorallocate($this->img,0xAA,0xAA,0xAA); imagerectangle($this->img,0,0,$this->width-1,$this->height-1,$border_color); } //生成驗證碼的字符串 private function create_code(){ $src="這是字典XXXXX"; $code=""; for($i=0;$i<$this->num;$i++){ $index=mt_rand(0,mb_strlen($src)-1); $code.= mb_substr($src,$index,1); //注意求多字節內容的長度時使用mb_擴展 } return $code; } //將生成的字符串畫在畫布上 private function paint_char(){ for($i=0;$i<$this->num;$i++){ $char_color=imagecolorallocate($this->img,0xFF,0,0xFF); $font_size=24; $x=5+($this->width/$this->num)*$i; $y=($this->height-imagefontheight($font_size)); imagettftext($this->img,$font_size,mt_rand(2, 20),$x,$y,$char_color,"STXINGKA.TTF",mb_substr($this->code,$i,1,"UTF-8")); //注意截取多字節的內容使用mb_擴展 } } //添加干擾標記 private function add_disturbance(){ for($i=0;$i<20;$i++){ $color=imagecolorallocate($this->img,rand(0,255),rand(0,255),rand(0,255)); imagesetpixel($this->img,rand(1,$this->width-2),rand(1,$this->height-2),$color); } } //輸出圖片 private function print_code() { if (imagetypes() & IMG_PNG) { header("Content-type: image/png"); imagepng($this->img); } elseif (imagetypes() & IMG_JPG) { header("Content-type: image/jpeg"); imagejpeg($this->img); } else { die("No image support in this PHP server"); } } //獲取驗證碼字符串的值 public function get_code(){ return $this->code; } //釋放資源 private function destroy_code(){ imagedestroy($this->img); } //搞定全部驗證碼的工做 public function show_image_code(){ $this->create_canvas(); $this->paint_char(); $this->add_disturbance(); $this->print_code(); $this->destroy_code(); } } session_start(); $captcha = new Captcha(200, 60, 4); $captcha->show_image_code(); $_SESSION['cap_v'] = $captcha->get_code(); ?>
<!DOCTYPE html> <html> <head> <title>中文驗證碼</title> <meta charset='utf-8'> </head> <body> <img id="captcha_img" border='1' src='./captcha.php' style="width: 100px; height: 30px"><br> <a href='' id="change_img">換一個?</a><br><br> <input type='text' id='cap_v'> <button id="btn">submit</button> </body> <script> var captcha_img = document.getElementById("captcha_img"); var change_img = document.getElementById("change_img"); var btn = document.getElementById("btn"); change_img = captcha_img.onclick = function(){ captcha_img.src='./captcha.php?r='+Math.random(); return false; } btn.onclick = function(){ var xhr = new XMLHttpRequest(); var cap_v = document.getElementById("cap_v").value; if( cap_v.trim().length == 0){ alert("驗證碼不能爲空"); return; } xhr.open("post","validate.php",true); xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded"); xhr.send("cap_v=" + cap_v); xhr.onreadystatechange = function(){ if(xhr.readyState==4){ if((xhr.status==200 && xhr.status<300) || xhr.status==304){ if(xhr.responseText == 'right'){ alert("歡迎"); } else { alert("驗證碼輸入錯誤"); } } } } } </script> </html>
<?php session_start(); if(isset($_POST['cap_v'])){ if($_SESSION['cap_v'] == trim($_POST['cap_v'])){ echo 'right'; } else { echo 'wrong'; } } ?>
運行截圖: