萬盛學電腦網

您现在的位置: 萬盛學電腦網 >> 程式設計 >  >> 網路程式設計 >> PHP 程式設計

PHP 圖形驗證碼生成與驗證完整實作教學

驗證碼機制原理

圖形驗證碼(CAPTCHA)透過生成機器難以辨識、人類易於閱讀的圖片,有效防止自動化腳本惡意註冊、暴力破解等攻擊。本文實作一個經典的 4 位數字驗證碼,包含干擾線、噪點與字元隨機偏移。

核心實作步驟

  1. 生成隨機碼:產生 4 位隨機數字並存入 Session
  2. 建立畫布:使用 GD 庫創建指定尺寸的圖片資源
  3. 繪製干擾元素:虛線、隨機噪點增加識別難度
  4. 渲染驗證碼文字:隨機位置、間距繪製各字元
  5. 輸出圖片:設定 Header 輸出 PNG 格式並銷毀資源

驗證碼生成程式 (captcha.php)

<?php
session_start();

// 1. 生成 4 位隨機數字
$code = '';
for ($i = 0; $i < 4; $i++) {
    $code .= mt_rand(0, 9);
}
// 替代寫法:$code = str_pad(mt_rand(0, 9999), 4, '0', STR_PAD_LEFT);

// 2. 存入 Session 供驗證使用
$_SESSION['captcha_code'] = $code;

// 3. 建立圖片畫布 (寬 100px, 高 35px)
$width = 100;
$height = 35;
$im = imagecreatetruecolor($width, $height);

// 4. 分配顏色
$bg_color = imagecolorallocate($im, 230, 230, 230);  // 淺灰背景
$text_color = imagecolorallocate($im, 0, 0, 0);       // 黑色文字
$line_color = imagecolorallocate($im, 150, 150, 150); // 灰色干擾線
$dot_color = imagecolorallocate($im, 100, 100, 100);  // 深灰噪點

// 5. 填充背景
imagefill($im, 0, 0, $bg_color);

// 6. 繪製干擾線 (3 條)
for ($i = 0; $i < 3; $i++) {
    imageline($im,
        mt_rand(0, $width), mt_rand(0, $height),
        mt_rand(0, $width), mt_rand(0, $height),
        $line_color
    );
}

// 7. 繪製噪點 (80 個)
for ($i = 0; $i < 80; $i++) {
    imagesetpixel($im, mt_rand(0, $width), mt_rand(0, $height), $dot_color);
}

// 8. 繪製驗證碼文字 (隨機位置與角度)
$font_size = 5; // 內建字體 1-5
$x = 10;
for ($i = 0; $i < 4; $i++) {
    $y = mt_rand(8, 22);
    $angle = mt_rand(-15, 15);
    // 使用 imagettftext 可載入 TTF 字體獲得更好效果
    imagestring($im, $font_size, $x, $y, $code[$i], $text_color);
    $x += mt_rand(18, 24); // 隨機字元間距
}

// 9. 輸出圖片並釋放資源
header('Content-Type: image/png');
imagepng($im);
imagedestroy($im);

前端表單整合 (register.php)

<form method="post" action="check_register.php">
    <div>
        <label>帳號:</label>
        <input type="text" name="username" required>
    </div>
    <div>
        <label>驗證碼:</label>
        <input type="text" name="captcha" maxlength="4" size="6" required>
        <img id="captchaImg" src="captcha.php" alt="驗證碼" style="vertical-align: middle; cursor: pointer;" title="點擊更換">
    </div>
    <button type="submit">註冊</button>
</form>

<script>
document.getElementById('captchaImg').onclick = function() {
    this.src = 'captcha.php?' + Date.now(); // 加時間戳防快取
};
</script>

後端驗證邏輯 (check_register.php)

<?php
session_start();

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $input_code = trim($_POST['captcha']);
    $session_code = $_SESSION['captcha_code'] ?? '';
    
    // 驗證碼比對 (不分大小寫,此處純數字無影響)
    if (strtolower($input_code) !== strtolower($session_code)) {
        die('驗證碼錯誤,請返回重試');
    }
    
    // 驗證通過,執行註冊邏輯...
    echo '註冊成功!';
    
    // 用完即銷毀,防止重複使用
    unset($_SESSION['captcha_code']);
}

進階強化方向

增強項目實作方式效果
字元類型擴充加入大小寫英文、特殊符號大幅提高破解難度
TTF 字體渲染使用 imagettftext + 自訂字體檔字體扭曲、旋轉更自然
幾何扭曲imageaffine / imagefilter 濾鏡干擾 OCR 辨識演算法
語音驗證碼TTS 生成音檔給視障用戶符合無障礙網頁規範
行為驗證整合 Google reCAPTCHA v3零互動、風險評分機制

安全性注意事項

  • Session 劫持防護:啟用 session.cookie_httponly、session.use_strict_mode
  • 驗證碼一次性:驗證後立即 unset,防止重放攻擊
  • 速率限制:同一 IP 短時間請求上限,防暴力嘗試
  • HTTPS 傳輸:確保驗證碼圖片與表單提交全程加密

常見問題

Q: 為什麼驗證碼圖片顯示不出來?
A: 檢查 PHP 是否安裝 GD 擴充套件 (php -m | grep gd),確認輸出前無任何空白字元或 BOM。
Q: Session 讀取不到值?
A: 確認所有檔案最開頭都有 session_start(),且在任何輸出前呼叫。
Q: 如何提高辨識率平衡安全性?
A: 調整干擾線密度、字元旋轉角度範圍,實測用戶通過率應 > 90%。
copyright © 萬盛學電腦網 all rights reserved