首頁  >  文章  >  後端開發  >  php實作動態隨機驗證碼機制(CAPTCHA)

php實作動態隨機驗證碼機制(CAPTCHA)

WBOY
WBOY原創
2016-08-08 09:30:011008瀏覽

php實作動態隨機驗證碼機制

      驗證碼(CAPTCHA)是「Completely Automated Public Turing test to tell Computers and Humans Apart」(全自動區分電腦與人類的圖靈測試)的縮寫,是一種區分使用者是電腦還是人類的公共全自動程式。可以防止:惡意破解密碼、刷票、論壇灌水,有效防止某個駭客對某一個特定註冊用戶用特定程序暴力破解方式進行不斷的登陸嘗試,實際上用驗證碼是現在很多網站通行的方式,我們利用比較簡易的方式實現了這個功能。

      這個問題可以由電腦產生並評判,但是必須只有人類才能解答。由於電腦無法解答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_sizey_size 的黑色圖像。 語法:resource imagecreatetruecolor ( int $width , int $height )

$im = imagecreatetruecolor(200,200);

第三步,在空白影像區域繪製填充背景

要有顏色填充器;imagecolorallocate -- 為一幅圖像分配顏色;語法:int imagecolorallocate ( resource $image , int $red , int $3$5) , $ $blue = imagecolorallocate($im,0,102,255);

將這個blue顏色填入背景上去;imagefill -- 區域填入;

語法:bool imagefill ( resource

$image
, int

$x , int $e imagefill($im,0,0,$blue); 第四步,在藍色的背景上輸入一些線條,文字等 顏色填充器

$white = imagecolorallocate($im,255,255,255);

畫兩條線段:imageline
imageline() 用

color 顏色在圖像 image

中從坐標
x1

y1

x2

y2 到左上角圖片(圖段)。 語法:bool imageline ( resource $image , int $x1 , int $y1 , int $x2 , int , int 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 , int $y , string $ imagestring($im,5,66,20,'jingwhale',$white); <h5>第五步,輸出最終圖形</h5> <p><em>imagepng() 將 GD 映像流(<code>image)以 PNG 格式輸出到標準輸出(通常為瀏覽器),或者如果用 filename 給出了檔案名稱則將其輸出到該檔案。 語法:bool imagepng ( resource $image [, string $filename ] )

imagepng($im);

第六步,我要將所有的資源全部清空

imagedestroy() 釋放與 image 相關的記憶體。 語法:bool imagedestroy ( resource $image )

imagedestroy($im);

其他頁面(html)呼叫所建立的圖形

範例程式碼如下:

<?<span>php
    </span><span>//</span><span>第一步,设置文件MIME类型</span>
    <span>header</span>('Content-Type: image/png;'<span>);
    
    </span><span>//</span><span>第二步,创建一个图形区域,图像背景</span>
    <span>$im</span> = imagecreatetruecolor(200,200<span>);
    
    </span><span>//</span><span>第三步,在空白图像区域绘制填充背景</span>
    <span>$blue</span> = imagecolorallocate(<span>$im</span>,0,102,255<span>);    
    imagefill(</span><span>$im</span>,0,0,<span>$blue</span><span>);
    
    </span><span>//</span><span>第四步,在蓝色的背景上输入一些线条,文字等</span>
    <span>$white</span> = imagecolorallocate(<span>$im</span>,255,255,255<span>);
    imageline(</span><span>$im</span>,0,0,200,200,<span>$white</span><span>);
    imageline(</span><span>$im</span>,200,0,0,200,<span>$white</span><span>);
    imagestring(</span><span>$im</span>,5,66,20,'Jing.Whale',<span>$white</span><span>);
    
    </span><span>//</span><span>第五步,输出最终图形</span>
    imagepng(<span>$im</span><span>);
    
    </span><span>//</span><span>第六步,我要将所有的资源全部清空</span>
    imagedestroy(<span>$im</span><span>);    
</span>?>

顯示效果:

二.建立動態驗證碼

附:代碼來源位址https://github.com/cnblogs-/php-captcha

1. 建立帶有驗證碼的圖片,並模糊背景

隨機碼採用16進位;模糊背景即在圖片背景加上線條、雪花等。

1)建立隨機碼
  

<span>for</span> (<span>$i</span>=0;<span>$i</span><<span>$_rnd_code</span>;<span>$i</span>++<span>) {
        </span><span>$_nmsg</span> .= <span>dechex</span>(<span>mt_rand</span>(0,15<span>));
    }</span>

string dechex ( int $number ),傳回一字串,包含有給定 number 參數的十六進位表示。

2)保存在session
 

<span>$_SESSION</span>['code'] = <span>$_nms</span>

3)創建圖片

<span>//</span><span>创建一张图像</span>
<span>$_img</span> = imagecreatetruecolor(<span>$_width</span>,<span>$_height</span><span>);

</span><span>//</span><span>白色</span>
<span>$_white</span> = imagecolorallocate(<span>$_img</span>,255,255,255<span>);

</span><span>//</span><span>填充</span>
imagefill(<span>$_img</span>,0,0,<span>$_white</span><span>);

</span><span>if</span> (<span>$_flag</span><span>) {
</span><span>//</span><span>黑色,边框</span>
    <span>$_black</span> = imagecolorallocate(<span>$_img</span>,0,0,0<span>);
    imagerectangle(</span><span>$_img</span>,0,0,<span>$_width</span>-1,<span>$_height</span>-1,<span>$_black</span><span>);
}</span>

4)模糊背景

<span>//</span><span>随即画出6个线条</span>
<span>for</span> (<span>$i</span>=0;<span>$i</span><6;<span>$i</span>++<span>) {
</span><span>   $_rnd_color</span> = imagecolorallocate(<span>$_img</span>,<span>mt_rand</span>(0,255),<span>mt_rand</span>(0,255),<span>mt_rand</span>(0,255<span>));
   imageline(</span><span>$_img</span>,<span>mt_rand</span>(0,<span>$_width</span>),<span>mt_rand</span>(0,<span>$_height</span>),<span>mt_rand</span>(0,<span>$_width</span>),<span>mt_rand</span>(0,<span>$_height</span>),<span>$_rnd_color</span><span>);
   }

</span><span>//随机</span><span>雪花</span>
<span>for</span> (<span>$i</span>=0;<span>$i</span><100;<span>$i</span>++<span>) {
   </span><span>$_rnd_color</span> = imagecolorallocate(<span>$_img</span>,<span>mt_rand</span>(200,255),<span>mt_rand</span>(200,255),<span>mt_rand</span>(200,255<span>));
   imagestring(</span><span>$_img</span>,1,<span>mt_rand</span>(1,<span>$_width</span>),<span>mt_rand</span>(1,<span>$_height</span>),'*',<span>$_rnd_color</span><span>);
   }</span>

5)輸出及銷毀

<span>//</span><span>输出验证码</span>
<span>for</span> (<span>$i</span>=0;<span>$i</span><<span>strlen</span>(<span>$_SESSION</span>['code']);<span>$i</span>++<span>) {
        </span><span>$_rnd_color</span> = imagecolorallocate(<span>$_img</span>,<span>mt_rand</span>(0,100),<span>mt_rand</span>(0,150),<span>mt_rand</span>(0,200<span>));
        imagestring(</span><span>$_img</span>,5,<span>$i</span>*<span>$_width</span>/<span>$_rnd_code</span>+<span>mt_rand</span>(1,10),<span>mt_rand</span>(1,<span>$_height</span>/2),<span>$_SESSION</span>['code'][<span>$i</span>],<span>$_rnd_color</span><span>);
    }

</span><span>//</span><span>输出图像</span>
<span>header</span>('Content-Type: image/png'<span>);
imagepng(</span><span>$_img</span><span>);

</span><span>//</span><span>销毁</span>
imagedestroy(<span>$_img</span>);

將其封裝在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無邊框(預設)

封裝後的程式碼如下:

<?<span>php 
</span><span>/*</span><span>*
 *      [verification-code] (C)2015-2100 jingwhale.
 *      
 *      This is a freeware
 *      $Id: global.func.php 2015-02-05 20:53:56 jingwhale$
 </span><span>*/</span>
<span>/*</span><span>*
 * _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 这个函数执行后产生一个验证码
 </span><span>*/</span>
<span>function</span> _code(<span>$_width</span> = 75,<span>$_height</span> = 25,<span>$_rnd_code</span> = 4,<span>$_flag</span> = <span>false</span><span>) {

    </span><span>//</span><span>创建随机码</span>
    <span>for</span> (<span>$i</span>=0;<span>$i</span><<span>$_rnd_code</span>;<span>$i</span>++<span>) {
        </span><span>$_nmsg</span> .= <span>dechex</span>(<span>mt_rand</span>(0,15<span>));
    }

    </span><span>//</span><span>保存在session</span>
    <span>$_SESSION</span>['code'] = <span>$_nmsg</span><span>;

    </span><span>//</span><span>创建一张图像</span>
    <span>$_img</span> = imagecreatetruecolor(<span>$_width</span>,<span>$_height</span><span>);

    </span><span>//</span><span>白色</span>
    <span>$_white</span> = imagecolorallocate(<span>$_img</span>,255,255,255<span>);

    </span><span>//</span><span>填充</span>
    imagefill(<span>$_img</span>,0,0,<span>$_white</span><span>);

    </span><span>if</span> (<span>$_flag</span><span>) {
        </span><span>//</span><span>黑色,边框</span>
        <span>$_black</span> = imagecolorallocate(<span>$_img</span>,0,0,0<span>);
        imagerectangle(</span><span>$_img</span>,0,0,<span>$_width</span>-1,<span>$_height</span>-1,<span>$_black</span><span>);
    }

    </span><span>//</span><span>随即画出6个线条</span>
    <span>for</span> (<span>$i</span>=0;<span>$i</span><6;<span>$i</span>++<span>) {
        </span><span>$_rnd_color</span> = imagecolorallocate(<span>$_img</span>,<span>mt_rand</span>(0,255),<span>mt_rand</span>(0,255),<span>mt_rand</span>(0,255<span>));
        imageline(</span><span>$_img</span>,<span>mt_rand</span>(0,<span>$_width</span>),<span>mt_rand</span>(0,<span>$_height</span>),<span>mt_rand</span>(0,<span>$_width</span>),<span>mt_rand</span>(0,<span>$_height</span>),<span>$_rnd_color</span><span>);
    }

    </span><span>//</span><span>随即雪花</span>
    <span>for</span> (<span>$i</span>=0;<span>$i</span><100;<span>$i</span>++<span>) {
        </span><span>$_rnd_color</span> = imagecolorallocate(<span>$_img</span>,<span>mt_rand</span>(200,255),<span>mt_rand</span>(200,255),<span>mt_rand</span>(200,255<span>));
        imagestring(</span><span>$_img</span>,1,<span>mt_rand</span>(1,<span>$_width</span>),<span>mt_rand</span>(1,<span>$_height</span>),'*',<span>$_rnd_color</span><span>);
    }

    </span><span>//</span><span>输出验证码</span>
    <span>for</span> (<span>$i</span>=0;<span>$i</span><<span>strlen</span>(<span>$_SESSION</span>['code']);<span>$i</span>++<span>) {
        </span><span>$_rnd_color</span> = imagecolorallocate(<span>$_img</span>,<span>mt_rand</span>(0,100),<span>mt_rand</span>(0,150),<span>mt_rand</span>(0,200<span>));
        imagestring(</span><span>$_img</span>,5,<span>$i</span>*<span>$_width</span>/<span>$_rnd_code</span>+<span>mt_rand</span>(1,10),<span>mt_rand</span>(1,<span>$_height</span>/2),<span>$_SESSION</span>['code'][<span>$i</span>],<span>$_rnd_color</span><span>);
    }

    </span><span>//</span><span>输出图像</span>
    <span>header</span>('Content-Type: image/png'<span>);
    imagepng(</span><span>$_img</span><span>);

    </span><span>//</span><span>销毁</span>
    imagedestroy(<span>$_img</span><span>);
}
</span>?>
2.創建驗證機制

建立php驗證頁面,透過session來檢驗驗證碼是否一致。

1)建立verification-code.php驗證頁面

<?<span>php 
</span><span>/*</span><span>*
 *      [verification-code] (C)2015-2100 jingwhale.
 *
 *      This is a freeware
 *      $Id: verification-code.php 2015-02-05 20:53:56 jingwhale$
 </span><span>*/</span>

<span>//</span><span>设置字符集编码</span>
<span>header</span>('Content-Type: text/html; charset=utf-8'<span>);
</span>?>

<!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>
        <form method="post" name="verification" action="verification-code.php?action=verification">
            <<span>dl</span>>
                <dd>验证码:<input type="text" name="code" <span>class</span>="code" /><img src="codeimg.php"  /></dd>
                <dd><input type="submit" <span>class</span>="submit" value="验证" /></dd>
            </<span>dl</span>>
        </form>
    </div>

</body>
</html>

顯示如下:

2)建立產生驗證碼頁面

創建codeimg.php為verification-code.php html程式碼裡的img提供驗證碼圖片

首先必須在codeimg.php頁面開啟session;

其次,將我們封裝好的global.func.php全域函數庫引入;

最後,運行_code();

<?<span>php 
</span><span>/*</span><span>*
 *      [verification-code] (C)2015-2100 jingwhale.
 *      
 *      This is a freeware
 *      $Id: codeimg.php 2015-02-05 20:53:56 jingwhale$
 </span><span>*/</span>

<span>//</span><span>开启session</span>
<span>session_start</span><span>();

</span><span>//</span><span>引入全局函数库(自定义)</span>
<span>require</span> <span>dirname</span>(<span>__FILE__</span>).'/includes/global.func.php'<span>;

</span><span>//</span><span>运行验证码函数。通过数据库的_code方法,设置验证码的各种属性,生成图片</span>
_code(125,25,6,<span>false</span><span>);

</span>?>

3)創建session檢驗機制

首先必須在verification-code.php頁面開啟session;

其次,設計提交驗證碼的方式,本文以get方式提交,當action=verification時提交成功;

最後,建立驗證函數,原理是將客戶端使用者提交的驗證碼同伺服器codeimg.php中session的驗證碼是否一致;這裡有一個js彈窗函數_alert_back(),我們也把它封裝在global. func.php裡;

修改verification-code.php中php程式碼如下:

<?<span>php 
</span><span>/*</span><span>*
 *      [verification-code] (C)2015-2100 jingwhale.
 *
 *      This is a freeware
 *      $Id: verification-code.php 2015-02-05 20:53:56 jingwhale$
 </span><span>*/</span>

<span>//</span><span>设置字符集编码</span>
<span>header</span>('Content-Type: text/html; charset=utf-8'<span>);

</span><span>//</span><span>开启session</span>
<span>session_start</span><span>();

</span><span>//</span><span>引入全局函数库(自定义)</span>
<span>require</span> <span>dirname</span>(<span>__FILE__</span>).'/includes/global.func.php'<span>;

</span><span>//</span><span>检验验证码</span>
<span>if</span> (<span>$_GET</span>['action'] == 'verification'<span>) {
    
    </span><span>if</span> (!(<span>$_POST</span>['code'] == <span>$_SESSION</span>['code'<span>])) {
        _alert_back(</span>'验证码不正确!'<span>);
    }</span><span>else</span><span>{
        _alert_back(</span>'验证码通过!'<span>);
    }
}  
</span>?>

<!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>
        <form method="post" name="verification" action="verification-code.php?action=verification">
            <<span>dl</span>>
                <dd>验证码:<input type="text" name="code" <span>class</span>="code" /><img src="codeimg.php"  /></dd>
                <dd><input type="submit" <span>class</span>="submit" value="验证" /></dd>
            </<span>dl</span>>
        </form>
    </div>

</body>
</html>

3.實現點擊驗證碼圖片更新驗證碼

上面若想實現驗證碼更新,必須刷新頁面;我們寫一個codeimg.js函數實作點擊驗證碼圖片更新驗證碼

window.onload = <span>function</span><span> () {
    </span><span>var</span> code = document.getElementById('codeimg');<span>//</span><span>通过id找到html中img标签</span>
    code.onclick = <span>function</span> () {<span>//</span><span>为标签添加点击事件</span>
        <span>this</span>.src='codeimg.php?tm='+Math.random();<span>//</span><span>修改时间,重新指向codeimg.php</span>
<span>    };    
}</span>

然後在verification-code.php html代碼head裡它即可。

歡迎轉載。轉載請註明轉載字樣,標示原作者及原博文地址。

以上就介紹了php實作動態隨機驗證碼機制(CAPTCHA),包含了面向的內容,希望對PHP教學有興趣的朋友有幫助。

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn