php實現動態隨機驗證碼機制
來源:互聯網
上載者:User
驗證碼(CAPTCHA)是“Completely Automated Public Turing test to tell Computers and Humans Apart”(全自動區分電腦和人類的圖靈測試)的縮寫,是一種區分使用者是電腦還是人的公用全Bot。可以防止:惡意破解密碼、刷票、論壇灌水,有效防止某個駭客對某一個特定註冊使用者用特定程式暴力破解方式進行不斷的登陸嘗試,實際上用驗證碼是現在很多網站通行的方式,我們利用比較簡易的方式實現了這個功能。 這個問題可以由電腦產生並評判,但是必須只有人類才能解答。由於電腦無法解答CAPTCHA的問題,所以回答出問題的使用者就可以被認為是人類。 Php製作動態驗證碼是基於php的影像處理,下面首先介紹一下php的影像處理。 一.php影像處理簡介 在PHP5中,動態圖象的處理要比以前容易得多。PHP5在php.ini檔案中包含了GD擴充包,只需去掉GD擴充包的相應注釋就可以正常使用了。PHP5包含的GD庫正是升級的GD2庫,其中包含支援真彩影像處理的一些有用的JPG功能。 一般產生的圖形,通過PHP的文檔格式存放,但可以通過HTML的圖片插入方式SRC來直接擷取動態圖形。比如,驗證碼、浮水印、微縮圖等。 建立映像的一般流程: 1).設定標題,告訴瀏覽器你要產生的MIME類型。 2).建立一個映像地區,以後的操作都將基於此映像地區。 3).在空白映像地區繪製填充背景。 4).在背景上繪製圖形輪廓輸入文本。 5).輸出最終圖形。 6).清除所有資源。 7).其他頁面調用映像。 第一步,設定檔案MIME類型,輸出類型 將輸出類型改成映像流header('Content-Type: image/png;'); 一般產生的映像可以是png,jpeg,gif,wbmp 第二步,建立一個繪圖區域,映像背景imagecreatetruecolor() 返回一個映像標識符,代表了一幅大小為 x_size 和 y_size 的黑色映像。文法:resource imagecreatetruecolor ( int $width , int $height ) $im = imagecreatetruecolor(200,200); 第三步,在空白映像地區繪製填充背景 要有顏色填充器;imagecolorallocate -- 為一幅映像分配顏色;文法:int imagecolorallocate ( resource $image , int $red , int $green , int $blue ) $blue = imagecolorallocate($im,0,102,255); 將這個blue顏色填充到背景上去;imagefill -- 地區填充;文法:bool imagefill ( resource $image , int $x , int $y , int $color ) imagefill($im,0,0,$blue); 第四步,在藍色的背景上輸入一些線條,文字等顏色填充器 $white = imagecolorallocate($im,255,255,255); 畫兩條線段:imageline imageline() 用 color 顏色在映像 image 中從座標 x1,y1 到 x2,y2(映像左上方為 0, 0)畫一條線段。文法:bool imageline ( resource $image , int $x1 , int $y1 , int $x2 , int $y2 , int $color ) imageline($im,0,0,200,200,$white); imageline($im,200,0,0,200,$white); 水平地畫一行字串:imagestring imagestring() 用 col 顏色將字串 s 畫到 image 所代表的映像的 x,y 座標處(這是字串左上方座標,整幅映像的左上方為 0,0)。如果font 是 1,2,3,4 或 5,則使用內建字型。文法:bool imagestring ( resource $image , int $font , int $x , int $y , string $s , int $col ) imagestring($im,5,66,20,'jingwhale',$white); 第五步,輸出最終圖形imagepng() 將 GD 映像流(image)以 PNG 格式輸出到標準輸出(通常為瀏覽器),或者如果用 filename 給出了檔案名稱則將其輸出到該檔案。文法:bool imagepng ( resource $image [, string $filename ] ) imagepng($im); 第六步,我要將所有的資源全部清空imagedestroy() 釋放與 image 關聯的記憶體。文法:bool imagedestroy ( resource $image ) imagedestroy($im); 其他頁面(html)調用建立的圖形<img src="Demo4.php" alt="PHP建立的圖片" /> 範例程式碼如下: 複製代碼<?php //第一步,設定檔案MIME類型 header('Content-Type: image/png;'); //第二步,建立一個繪圖區域,映像背景 $im = imagecreatetruecolor(200,200); //第三步,在空白映像地區繪製填充背景 $blue = imagecolorallocate($im,0,102,255); imagefill($im,0,0,$blue); //第四步,在藍色的背景上輸入一些線條,文字等 $white = imagecolorallocate($im,255,255,255); imageline($im,0,0,200,200,$white); imageline($im,200,0,0,200,$white); imagestring($im,5,66,20,'Jing.Whale',$white); //第五步,輸出最終圖形 imagepng($im); //第六步,我要將所有的資源全部清空 imagedestroy($im); ?>複製代碼顯示效果: image 二.建立動態驗證碼附:代碼源地址https://github.com/cnblogs-/php-captcha 1. 建立帶驗證碼的圖片,並模糊背景隨機碼採用16進位;模糊背景即在圖片背景加上線條、雪花等。 1)建立隨機碼 for ($i=0;$i<$_rnd_code;$i++) { $_nmsg .= dechex(mt_rand(0,15)); }string dechex ( int $number ),返回一字串,包含有給定 number 參數的十六進位表示。 2)儲存在session $_SESSION['code'] = $_nms3)建立圖片 複製代碼//建立一張映像$_img = imagecreatetruecolor($_width,$_height); //白色$_white = imagecolorallocate($_img,255,255,255); //填充imagefill($_img,0,0,$_white); if ($_flag) {//黑色,邊框 $_black = imagecolorallocate($_img,0,0,0); imagerectangle($_img,0,0,$_width-1,$_height-1,$_black);}複製代碼4)模糊背景 複製代碼//隨機畫出6個線條for ($i=0;$i<6;$i++) { $_rnd_color = imagecolorallocate($_img,mt_rand(0,255),mt_rand(0,255),mt_rand(0,255)); imageline($_img,mt_rand(0,$_width),mt_rand(0,$_height),mt_rand(0,$_width),mt_rand(0,$_height),$_rnd_color); } //隨機雪花for ($i=0;$i<100;$i++) { $_rnd_color = imagecolorallocate($_img,mt_rand(200,255),mt_rand(200,255),mt_rand(200,255)); imagestring($_img,1,mt_rand(1,$_width),mt_rand(1,$_height),'*',$_rnd_color); }複製代碼5)輸出及銷毀 複製代碼//輸出驗證碼for ($i=0;$i<strlen($_SESSION['code']);$i++) { $_rnd_color = imagecolorallocate($_img,mt_rand(0,100),mt_rand(0,150),mt_rand(0,200)); imagestring($_img,5,$i*$_width/$_rnd_code+mt_rand(1,10),mt_rand(1,$_height/2),$_SESSION['code'][$i],$_rnd_color); } //輸出映像header('Content-Type: image/png');imagepng($_img); //銷毀imagedestroy($_img);複製代碼將其封裝在global.func.php全域函數庫中,函數名為_code(),以便調用。我們將設定$_width ,$_height ,$_rnd_code,$_flag 四個參數,以增強函數的靈活性。 * @param int $_width 驗證碼的長度:如果要6位長度推薦75+50;如果要8位,推薦75+50+50,依次類推* @param int $_height 驗證碼的高度* @param int $_rnd_code 驗證碼的位元* @param bool $_flag 驗證碼是否需要邊框:true有邊框, false無邊框(預設) 封裝後的代碼如下: 複製代碼<?php /** * [verification-code] (C)2015-2100 jingwhale. * * This is a freeware * $Id: global.func.php 2015-02-05 20:53:56 jingwhale$ *//** * _code()是驗證碼函數 * @access public * @param int $_width 驗證碼的長度:如果要6位長度推薦75+50;如果要8位,推薦75+50+50,依次類推 * @param int $_height 驗證碼的高度 * @param int $_rnd_code 驗證碼的位元 * @param bool $_flag 驗證碼是否需要邊框:true有邊框, false無邊框(預設) * @return void 這個函數執行後產生一個驗證碼 */function _code($_width = 75,$_height = 25,$_rnd_code = 4,$_flag = false) { //建立隨機碼 for ($i=0;$i<$_rnd_code;$i++) { $_nmsg .= dechex(mt_rand(0,15)); } //儲存在session $_SESSION['code'] = $_nmsg; //建立一張映像 $_img = imagecreatetruecolor($_width,$_height); //白色 $_white = imagecolorallocate($_img,255,255,255); //填充 imagefill($_img,0,0,$_white); if ($_flag) { //黑色,邊框 $_black = imagecolorallocate($_img,0,0,0); imagerectangle($_img,0,0,$_width-1,$_height-1,$_black); } //隨即畫出6個線條 for ($i=0;$i<6;$i++) { $_rnd_color = imagecolorallocate($_img,mt_rand(0,255),mt_rand(0,255),mt_rand(0,255)); imageline($_img,mt_rand(0,$_width),mt_rand(0,$_height),mt_rand(0,$_width),mt_rand(0,$_height),$_rnd_color); } //隨即雪花 for ($i=0;$i<100;$i++) { $_rnd_color = imagecolorallocate($_img,mt_rand(200,255),mt_rand(200,255),mt_rand(200,255)); imagestring($_img,1,mt_rand(1,$_width),mt_rand(1,$_height),'*',$_rnd_color); } //輸出驗證碼 for ($i=0;$i<strlen($_SESSION['code']);$i++) { $_rnd_color = imagecolorallocate($_img,mt_rand(0,100),mt_rand(0,150),mt_rand(0,200)); imagestring($_img,5,$i*$_width/$_rnd_code+mt_rand(1,10),mt_rand(1,$_height/2),$_SESSION['code'][$i],$_rnd_color); } //輸出映像 header('Content-Type: image/png'); imagepng($_img); //銷毀 imagedestroy($_img);}?>複製代碼2.建立驗證機制建立php驗證頁面,通過session來檢驗驗證碼是否一致。 1)建立verification-code.php驗證頁面 複製代碼<?php /** * [verification-code] (C)2015-2100 jingwhale. * * This is a freeware * $Id: verification-code.php 2015-02-05 20:53:56 jingwhale$ */ //設定字元集編碼header('Content-Type: text/html; charset=utf-8');?> <!DOCTYPE html><html><head> <meta charset="UTF-8"> <title>verification code</title> <link rel="stylesheet" type="text/css" href="style/basic.css" /></head><body> <div id="testcode"> <form method="post" name="verification" action="verification-code.php?action=verification"> <dl> <dd>驗證碼:<input type="text" name="code" class="code" /><img src="codeimg.php" id="codeimg" /></dd> <dd><input type="submit" class="submit" value="驗證" /></dd> </dl> </form> </div> </body></html>複製代碼顯示如下: image 2)建立產生驗證碼圖片頁面 建立codeimg.php為verification-code.php html代碼裡的img提供驗證碼圖片 首先必須在codeimg.php頁面開啟session; 其次,將我們封裝好的global.func.php全域函數庫引入進來; 最後,運行_code(); 複製代碼<?php /** * [verification-code] (C)2015-2100 jingwhale. * * This is a freeware * $Id: codeimg.php 2015-02-05 20:53:56 jingwhale$ */ //開啟sessionsession_start(); //引入全域函數庫(自訂)require dirname(__FILE__).'/includes/global.func.php'; //運行驗證碼函數。通過資料庫的_code方法,設定驗證碼的各種屬性,產生圖片_code(125,25,6,false); ?>複製代碼image 3)建立session檢驗機制 首先必須在verification-code.php頁面也開啟session; 其次,設計提交驗證碼的方式,本文以get方式提交,當action=verification時提交成功; 最後,建立驗證函式,原理是將用戶端使用者提交的驗證碼同伺服器codeimg.php中session的驗證碼是否一致;這裡有一個js彈窗函數_alert_back(),我們也把它封裝在global.func.php裡; 修改verification-code.php中php代碼如下: 複製代碼<?php /** * [verification-code] (C)2015-2100 jingwhale. * * This is a freeware * $Id: verification-code.php 2015-02-05 20:53:56 jingwhale$ */ //設定字元集編碼header('Content-Type: text/html; charset=utf-8'); //開啟sessionsession_start(); //引入全域函數庫(自訂)require dirname(__FILE__).'/includes/global.func.php'; //檢驗驗證碼if ($_GET['action'] == 'verification') { if (!($_POST['code'] == $_SESSION['code'])) { _alert_back('驗證碼不正確!'); }else{ _alert_back('驗證碼通過!'); }} ?> <!DOCTYPE html><html><head> <meta charset="UTF-8"> <title>verification code</title> <link rel="stylesheet" type="text/css" href="style/basic.css" /> <script type="text/javascript" src="js/codeimg.js"></script></head><body> <div id="testcode"> <form method="post" name="verification" action="verification-code.php?action=verification"> <dl> <dd>驗證碼:<input type="text" name="code" class="code" /><img src="codeimg.php" id="codeimg" /></dd> <dd><input type="submit" class="submit" value="驗證" /></dd> </dl> </form> </div> </body></html> 1 3.實現點擊驗證碼圖片更新驗證碼上面若想實現驗證碼更新,必須重新整理頁面;我們寫一個codeimg.js函數實現點擊驗證碼圖片更新驗證碼 複製代碼window.onload = function () { var code = document.getElementById('codeimg');//通過id找到html中img標籤 code.onclick = function () {//為標籤添加點擊事件 this.src='codeimg.php?tm='+Math.random();//修改時間,重新指向codeimg.php }; }