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

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

      驗證碼(CAPTCHA)是「Completely Automated Public Turing test to tell Computers and Humans Apart」(全自動區分計算機和人類的圖靈測試)的縮寫,是一種區分用戶是計算機仍是人的公共全自動程序。能夠防止:惡意破解密碼、刷票、論壇灌水,有效防止某個黑客對某一個特定註冊用戶用特定程序暴力破解方式進行不斷的登錄嘗試,實際上用驗證碼是如今不少網站通行的方式,咱們利用比較簡易的方式實現了這個功能。javascript

      這個問題能夠由計算機生成並評判,可是必須只有人類才能解答。因爲計算機沒法解答CAPTCHA的問題,因此回答出問題的用戶就能夠被認爲是人類。php

      Php製做動態驗證碼是基於php的圖像處理,下面首先介紹一下php的圖像處理。css

一.php圖像處理簡介

      在PHP5中,動態圖象的處理要比之前容易得多。PHP5在php.ini文件中包含了GD擴展包,只需去掉GD擴展包的相應註釋就能夠正常使用了。PHP5包含的GD庫正是升級的GD2庫,其中包含支持真彩圖像處理的一些有用的JPG功能。html

      通常生成的圖形,經過PHP的文檔格式存放,但能夠經過HTML的圖片插入方式SRC來直接獲取動態圖形。好比,驗證碼、水印、微縮圖等。java

      建立圖像的通常流程:git

1).設定標頭,告訴瀏覽器你要生成的MIME類型。github

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 $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 中從座標 x1y1x2y2(圖像左上角爲 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 所表明的圖像的 xy 座標處(這是字符串左上角座標,整幅圖像的左上角爲 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'] = $_nms

3)建立圖片

//建立一張圖像
$_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$
 */

//開啓session
session_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');

//開啓session
session_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
    };    
}

而後在verification-code.php html代碼head裏<link>它便可。

2

轉載需註明轉載字樣,標註原做者和原博文地址。

相關文章
相關標籤/搜索