首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

PHP 從零手寫驗證碼:隨機字元、GD 繪圖、Session 驗證完整流程

     編輯:PHP 相關知識

驗證碼核心流程

  1. 產生隨機碼:決定長度、字元集,存入 $_SESSION。
  2. 建立畫布:imagecreatetruecolor() 設定寬高。
  3. 分配顏色:背景色、文字色、干擾線色。
  4. 繪製干擾:隨機線條、噪點、背景雜訊。
  5. 繪製文字:imagettftext() (TTF 字型) 或 imagestring() (內建字型)。
  6. 輸出圖片:送出 Content-Type: image/jpeg 標頭,imagejpeg() 輸出。
  7. 銷毀資源:imagedestroy() 釋放記憶體。

完整可用範例 captcha.php

<?php
session_start();

// 1. 設定參數
$width = 120;
$height = 40;
$codeLen = 4;
$charset = '23456789ABCDEFGHJKLMNPQRSTUVWXYZ'; // 排除易混淆字元

// 2. 產生隨機碼
$code = '';
for ($i = 0; $i < $codeLen; $i++) {
    $code .= $charset[random_int(0, strlen($charset) - 1)];
}
$_SESSION['captcha'] = strtoupper($code); // 不分大小寫驗證時統一大寫

// 3. 建立真彩色畫布
$img = imagecreatetruecolor($width, $height);

// 4. 分配顏色
$bgColor = imagecolorallocate($img, 240, 240, 240); // 淺灰背景
$textColor = imagecolorallocate($img, 50, 50, 50);
$noiseColor = imagecolorallocate($img, 180, 180, 180);

// 填滿背景
imagefill($img, 0, 0, $bgColor);

// 5. 繪製干擾線 (5 條)
for ($i = 0; $i < 5; $i++) {
    imageline($img,
        random_int(0, $width), random_int(0, $height),
        random_int(0, $width), random_int(0, $height),
        $noiseColor
    );
}

// 6. 繪製干擾點 (50 個)
for ($i = 0; $i < 50; $i++) {
    imagesetpixel($img, random_int(0, $width), random_int(0, $height), $noiseColor);
}

// 7. 繪製驗證碼文字 (使用內建字型,簡單部署)
$fontSize = 5; // 1-5
$x = 10;
$y = 28;
for ($i = 0; $i < $codeLen; $i++) {
    $char = $code[$i];
    // 隨機旋轉角度 -15~15 度 (需 imagettftext + TTF 字型)
    // 這裡用 imagestring 簡單示範
    imagestring($img, $fontSize, $x, $y, $char, $textColor);
    $x += imagefontwidth($fontSize) + 2;
}

// 8. 輸出
header('Content-Type: image/jpeg');
header('Cache-Control: no-store, no-cache, must-revalidate');
header('Pragma: no-cache');
imagejpeg($img, null, 90);
imagedestroy($img);

前端調用

<img id="captchaImg" src="captcha.php" alt="驗證碼" style="cursor:pointer;vertical-align:middle" title="點擊更換" />
<input type="text" name="captcha_input" maxlength="4" />
<script>
document.getElementById('captchaImg').onclick = function() {
    this.src = 'captcha.php?' + Date.now(); // 防快取
};
</script>

後端驗證

<?php
session_start();
$input = strtoupper(trim($_POST['captcha_input'] ?? ''));
$valid = !empty($_SESSION['captcha']) && hash_equals($_SESSION['captcha'], $input);

// 安全:驗證後立即銷毀,防重放
unset($_SESSION['captcha']);

if ($valid) {
    echo '驗證通過';
} else {
    echo '驗證碼錯誤';
}

進階強化建議

  • TTF 字型 + 旋轉/扭曲:下載開源字型 (如 Noto Sans),用 imagettftext() 逐字繪製並套用隨機角度、字間距,大幅提高 OCR 識別難度。
  • Session 防暴力:限制同一 Session 最多產生 N 次驗證碼,或加入 IP 限流。
  • 無障礙替代:提供語音驗證碼或簡單算術題 (如 3+5=?) 給視障用戶。
  • 現代替代方案:考慮 Google reCAPTCHA v3、hCaptcha、Turnstile 等行為分析型驗證,零干擾且安全性更高。

常見問題排查

現象可能原因解決
圖片顯示破圖腳本有 BOM、空白輸出、錯誤訊息混入圖片二進位檔案存 UTF-8 無 BOM;error_reporting(0);確保 header() 前無任何輸出
Session 讀不到session_start() 未在最前面、Cookie 被封鎖確保 session_start() 在任何輸出前;檢查 session.cookie_secure/httponly 設定
字元重疊/截斷畫布寬度不足、字型過大依字元數 × 字寬 + 間距 計算最小寬度
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved