iT邦幫忙

DAY 27
2

遭遇PHP之經驗分享系列 第 27

[鐵人賽Day27]Captcha驗證碼分析與實作

  • 分享至 

  • xImage
  •  

今天想討論的是驗證碼的部分,在學習的過程中,總是覺得多一道驗證碼,好像比較安全
但當做好文字版的驗證碼,又擔心會不會有機器人攻擊
那用圖形驗證碼,說不定會比較安全吧...(猜測)
找尋了一下Google大神,找到了有人分享的這個資訊(http://jingyan.baidu.com/article/7f41ecece8025b593d095c1e.html)
分析了一下,查了一下使用的函數,也順便做了個小介面,套了個簡單的Javascript以及最重要的Check動作了

今天會用到的函數,有以下幾個:
imagecreate():建立一幅空白圖像
使用方法:imagecreate ( int $width , int $height )
$width:圖像的寬度
$height:圖像的高度
(參考資料:http://php.net/manual/en/function.imagecreate.php)

imagecolorallocate():分配圖像的顏色
使用方法:imagecolorallocate ( $image , $red , $green , $blue )
$image:圖像資源,通過圖像產生功能
顏色由RGB成份所組成
$red:紅色的數值
$green:綠色的數值
$blue:藍色的數值
(參考資料:http://php.net/manual/en/function.imagecolorallocate.php)

imagefilledrectangle():產生一個矩形圖像並填滿指定顏色
使用方法:imagefilledrectangle ( $image , $x1 , $y1 , $x2 , $y2 , $color )
$image:圖像資源,通過圖像產生功能
$x1:左上x坐標點
$y1:左上y坐標點
$x2:右下x坐標點
$y2:右下y坐標點
$color:填滿顏色
(參考資料:http://php.net/manual/en/function.imagefilledrectangle.php)

imagerectangle():產生一個指定顏色的矩形
imagerectangle ( $image , $x1 , $y1 , $x2 , $y2 , $color )
$image:圖像資源,通過圖像產生功能
$x1:左上x坐標點
$y1:左上y坐標點
(0,0是圖像的左上角)
$x2:右下x坐標點
$y2:右下y坐標點
$color:填滿指定顏色
(參考資料:http://php.net/manual/en/function.imagerectangle.php)

imagesetpixel():設定單一像素
使用方法:imagesetpixel ( $image , $x , $y , $color )\
$image:圖像資源,通過圖像產生功能
$x:x坐標點
$y:y坐標點
$color:填滿指定顏色
(參考資料:http://php.net/manual/en/function.imagesetpixel.php)

imagestring():
使用方法:imagestring ( $image, $font, $x, $y, $string, $color )
$image:圖像資源,通過圖像產生功能
$font:指定字型,有1,2,3,4 ,5,使用內建字型
$x:x坐標點
$y:y坐標點
$string:將要寫入的字串
$color:填滿指定顏色
(參考資料:http://php.net/manual/en/function.imagestring.php)

imagepng():以PNG格式將圖像輸出
使用方法:imagepng ( $image )
$image:圖像資源,通過圖像產生功能
(參考資料:http://php.net/manual/en/function.imagepng.php)

imagedestroy():釋放與圖像相關的任何資源
使用方法:imagedestroy ( $image )
$image:圖像資源,通過圖像產生功能
(參考資料:http://php.net/manual/en/function.imagedestroy.php)

-----------------我是分隔線-----------------

接下來,實作驗證碼的功能,程式碼如下方所示:
操作介面:「captcha_index.php」

    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>php圖形驗證碼</title>
   
    <script>
        function refresh_code(){ 
            document.getElementById("imgcode").src="captcha.php"; 
        } 
    </script>
    


    <form name="form1" method="post" action="./checkcode.php">
        <p>請輸入下圖字樣:</p><p><img id="imgcode" src="captcha.php" onclick="refresh_code()" /><br />
           點擊圖片可以更換驗證碼
        </p>
        <input type="text" name="checkword" size="10" maxlength="10" />
        <input type="submit" name="Submit" value="送出" />
    </form>

產生驗證碼:「captcha.php」

<?php
    if(!isset($_SESSION)){ session_start(); } //檢查SESSION是否啟動
        $_SESSION['check_word'] = ''; //設置存放檢查碼的SESSION

    //設置定義為圖片
    header("Content-type: image/PNG");

    /*
      imgcode($nums,$width,$high)
      設置產生驗證碼圖示的參數
      $nums 生成驗證碼個數
      $width 圖片寬
      $high 圖片高
    */
    imgcode(5,120,30);

    //imgcode的function
    function imgcode($nums,$width,$high) {
       
        //去除了數字0和1 字母小寫O和L,為了避免辨識不清楚
        $str = "23456789abcdefghijkmnpqrstuvwxyzABCDEFGHIJKLMOPQRSTUBWXYZ";
        $code = '';
        for ($i = 0; $i < $nums; $i++) {
            $code .= $str[mt_rand(0, strlen($str)-1)];
        }

        $_SESSION['check_word'] = $code;

        //建立圖示,設置寬度及高度與顏色等等條件
        $image = imagecreate($width, $high);
        $black = imagecolorallocate($image, mt_rand(0, 200), mt_rand(0, 200), mt_rand(0, 200));
        $border_color = imagecolorallocate($image, 21, 106, 235);
        $background_color = imagecolorallocate($image, 235, 236, 237);

        //建立圖示背景
        imagefilledrectangle($image, 0, 0, $width, $high, $background_color);

        //建立圖示邊框
        imagerectangle($image, 0, 0, $width-1, $high-1, $border_color);

        //在圖示布上隨機產生大量躁點
        for ($i = 0; $i < 80; $i++) {
            imagesetpixel($image, rand(0, $width), rand(0, $high), $black);
        }
       
        $strx = rand(3, 8);
        for ($i = 0; $i < $nums; $i++) {
            $strpos = rand(1, 6);
            imagestring($image, 5, $strx, $strpos, substr($code, $i, 1), $black);
            $strx += rand(10, 30);
        }

        imagepng($image);
        imagedestroy($image);
    }
?>

驗證輸入的驗證碼是否正確:「checkcode.php」

<?php
if(!isset($_SESSION)){
    session_start();
    }  //判斷session是否已啟動

if((!empty($_SESSION['check_word'])) && (!empty($_POST['checkword']))){  //判斷此兩個變數是否為空
    
     if($_SESSION['check_word'] == $_POST['checkword']){
         
          $_SESSION['check_word'] = ''; //比對正確後,清空將check_word值
         
          header('content-Type: text/html; charset=utf-8');
         
          echo '<p> </p><p> </p><a href="./chptcha_index.php">OK輸入正確,將於一秒後跳轉(按此也可返回)</a>';
         echo '<meta http-equiv="refresh" content="1; url=./captcha_index.php">';
         
          exit();
     }else{
         echo '<p> </p><p> </p><a href="./chptcha_index.php">Error輸入錯誤,將於一秒後跳轉(按此也可返回)</a>';
         echo '<meta http-equiv="refresh" content="1; url=./captcha_index.php">';
     }

}
?>

輸出畫面如圖所示:


上一篇
[鐵人賽Day26]jQuery AJAX部分的應用
下一篇
[鐵人賽Day28]PHP連結SQL Server(MSSQL)的方法與測試連線
系列文
遭遇PHP之經驗分享30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

2 則留言

0
Oo_花之舞__oO
iT邦新手 1 級 ‧ 2023-04-25 15:36:34

似乎無效

Old Siao iT邦研究生 1 級 ‧ 2023-04-25 16:11:00 檢舉

Img
剛試了一下在 PHP Version 8.2.5 環境下還是很正常的唷
您的似乎無效,是不是您Copy Code時漏了呢

0
btr
iT邦新手 5 級 ‧ 2023-09-01 21:44:33

我測試過也出現圖片無法顯示的問題
是修改php.ini檔後解決的https://ithelp.ithome.com.tw/upload/images/20230901/20162690mZLgsM9cuO.png
如圖
將;extension=gd的分號修改後,將apache重啟測試有沒有啟用

我要留言

立即登入留言