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

PHP GD 庫生成驗證碼完整教程:從基礎到抗機器識別強化

     編輯:PHP 相關知識

驗證碼核心作用

  • 區分人機,防止自動化腳本註冊、暴力破解、刷票、垃圾評論
  • 增加攻擊成本,配合限流、行為分析構建多層防禦

基礎版:字母數字混合 + 干擾點 + 邊框

<?php
// captcha.php
session_start();

// 1. 產生隨機字串
function generateCode($len = 4) {
  $chars = 'ABCDEFGHJKLMNPQRSTUVWXYZ23456789'; // 排除易混淆字元
  $code = '';
  for ($i = 0; $i < $len; $i++) {
    $code .= $chars[random_int(0, strlen($chars) - 1)];
  }
  return strtoupper($code);
}

$code = generateCode(4);
$_SESSION['captcha_code'] = $code;

// 2. 畫布設定
$width = 120;
$height = 40;
$img = imagecreatetruecolor($width, $height);

// 3. 顏色分配
$bg = imagecolorallocate($img, 245, 245, 245);      // 淺灰背景
$noise = imagecolorallocate($img, 180, 200, 220);   // 干擾點顏色
$text = imagecolorallocate($img, 30, 80, 180);      // 文字顏色
$border = imagecolorallocate($img, 150, 150, 150);  // 邊框

// 4. 填背景
imagefilledrectangle($img, 0, 0, $width, $height, $bg);

// 5. 畫干擾點
for ($i = 0; $i < 200; $i++) {
  imagesetpixel($img, random_int(0, $width), random_int(0, $height), $noise);
}

// 6. 畫干擾線(可選)
for ($i = 0; $i < 5; $i++) {
  imageline($img, 
    random_int(0, $width), random_int(0, $height),
    random_int(0, $width), random_int(0, $height),
    imagecolorallocate($img, random_int(150,200), random_int(150,200), random_int(150,200))
  );
}

// 7. 繪製文字(使用 TTF 字體更美觀、難識別)
$font = __DIR__ . '/fonts/arial.ttf'; // 需自備字體檔
if (file_exists($font)) {
  imagettftext($img, 20, 0, 15, 30, $text, $font, $code);
} else {
  // 內建字體備援
  imagestring($img, 5, 25, 10, $code, $text);
}

// 8. 邊框
imagerectangle($img, 0, 0, $width-1, $height-1, $border);

// 9. 輸出
header('Content-Type: image/png');
header('Cache-Control: no-store, no-cache, must-revalidate');
header('Pragma: no-cache');
imagepng($img);
imagedestroy($img);

前端調用

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

後端驗證

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

if ($valid) {
  // 驗證成功,清除防重複使用
  unset($_SESSION['captcha_code']);
  echo "驗證通過";
} else {
  echo "驗證碼錯誤";
}

進階強化:對抗 OCR/機器學習識別

手段實現要點效果
字體扭曲/旋傾imagettftext 每字隨機角度 ±15°、隨機字距⭐⭐⭐⭐
干擾線/曲線貝塞爾曲線、正弦波干擾線,顏色接近文字⭐⭐⭐
背景紋理漸層、噪點圖案、隨機幾何圖形⭐⭐
字元粘連/重疊故意讓字元邊界模糊、部分重疊⭐⭐⭐⭐
中文驗證碼從常用字庫隨機取 4-5 字,字體檔較大⭐⭐⭐⭐⭐
點選/滑動/拼圖前端 Canvas 交互,後端驗證軌跡/座標⭐⭐⭐⭐⭐ (現代主流)

進階版:字元隨機旋轉 + 位置抖動

<?php
// 在繪製文字處替換為:
$fontFile = __DIR__ . '/fonts/SourceSansPro-Bold.ttf';
$fontSize = 24;
$x = 15;
for ($i = 0; $i < strlen($code); $i++) {
  $char = $code[$i];
  $angle = random_int(-15, 15);
  $y = 30 + random_int(-3, 3); // 垂直抖動
  imagettftext($img, $fontSize, $angle, $x, $y, $text, $fontFile, $char);
  $x += $fontSize * 0.7 + random_int(0, 5); // 字距隨機
}

現代替代方案(強烈建議生產環境使用)

  1. Google reCAPTCHA v3:無感分數制,不打擾用戶
  2. hCaptcha:隱私友好、支援中文、有收益分成
  3. Geetest / 阿里云驗證碼 / 騰訊防水牆:國內訪問快、滑動/點選/無感多模式
  4. Turnstile (Cloudflare):免費、無 Cookie、易整合

安全檢查清單

  • ✅ Session 驗證碼驗證後立即銷毀(防重放)
  • ✅ 使用 hash_equals() 防時序攻擊
  • ✅ 圖片響應頭禁止快取
  • ✅ 限制單 IP 請求頻率(如 10 次/分鐘)
  • ✅ 字體檔案放在 Web 目錄外,防止直接下載分析
  • ✅ 記錄驗證失敗日誌,異常 IP 自動封禁

常見問題

問題原因解決
圖片不顯示/破圖輸出前有空白/BOM、錯誤訊息混入關閉 error_display、確保無輸出、檢查 GD 擴展
Session 驗證總失敗session_start() 未在最前、域名/路徑不一致統一 session 配置、檢查 cookie_domain
中文亂碼/方塊字體不支援中文使用 Noto Sans CJK、思源黑體等完整中文字體
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved