圖形驗證碼是防止機器人惡意註冊、暴力破解的基礎防線。本文詳細講解基於 GD 庫生成 PNG 驗證碼的完整流程,含干擾線、噪點、字符扭曲等反識別技術,並給出生產環境安全建議。
imagecreate() 或 imagecreatetruecolor()imagecolorallocate()(首次調用即填充背景)imagettftext() 隨機旋轉角度、隨機 Y 軸偏移imageline() 隨機顏色、位置imagesetpixel()header('Content-Type: image/png') + imagepng()imagedestroy()<?php
session_start();
header('Content-Type: image/png');
// 1. 畫布尺寸
$width = 130;
$height = 45;
$im = imagecreatetruecolor($width, $height);
// 2. 隨機背景色 (較淺)
$bg = imagecolorallocate($im, rand(180, 255), rand(180, 255), rand(180, 255));
imagefill($im, 0, 0, $bg);
// 3. 字體顏色 (較深) 與字體文件
$fontColor = imagecolorallocate($im, rand(0, 100), rand(0, 100), rand(0, 100));
$fontFile = __DIR__ . '/fonts/arial.ttf'; // 需確保字體文件存在
// 4. 生成 4 位隨機驗證碼
$code = '';
for ($i = 0; $i < 4; $i++) {
// 數字 0-9 或 大寫字母 A-Z
$char = chr(rand(0, 1) ? rand(48, 57) : rand(65, 90));
$code .= $char;
// 5. 繪製字符:隨機角度 ±25°,X 間距 30px,Y 隨機 30-35px
$angle = rand(-25, 25);
$x = 10 + $i * 28;
$y = rand(30, 38);
imagettftext($im, 24, $angle, $x, $y, $fontColor, $fontFile, $char);
}
// 存入 Session (供驗證時比對)
$_SESSION['authcode'] = strtolower($code); // 不區分大小寫
// 6. 干擾線 (6-10 條)
for ($i = 0; $i < rand(6, 10); $i++) {
$lineColor = imagecolorallocate($im, rand(100, 200), rand(100, 200), rand(100, 200));
imageline($im, rand(0, $width), 0, rand(0, $width), $height, $lineColor);
}
// 7. 噪點 (100-200 個)
for ($i = 0; $i < rand(100, 200); $i++) {
$noiseColor = imagecolorallocate($im, rand(0, 255), rand(0, 255), rand(0, 255));
imagesetpixel($im, rand(0, $width), rand(0, $height), $noiseColor);
}
// 8. 輸出與銷毀
imagepng($im);
imagedestroy($im);
?>
<img id="captcha" src="authcode.php" alt="驗證碼" style="cursor:pointer;vertical-align:middle" onclick="this.src='authcode.php?'+Math.random()" /> <input type="text" name="captcha_input" placeholder="點擊圖片換一張" />
<?php
session_start();
if (strtolower($_POST['captcha_input']) !== ($_SESSION['authcode'] ?? '')) {
die('驗證碼錯誤');
}
// 通過後清除,防止重放
unset($_SESSION['authcode']);
?>
| 風險點 | 對策 |
|---|---|
| OCR 識別破解 | 增加字符扭曲、重疊、波浪紋理、背景圖片干擾;或升級為行為驗證碼(滑塊/點選) |
| Session 劫持/重放 | 驗證後立即銷毀 Session 驗證碼;限制驗證碼有效期(如 5 分鐘) |
| 暴力遍歷 | 限制同 IP 刷新/驗證頻率(Redis 計數器);失敗 N 次鎖定 |
| 字體文件缺失 | 部署時打包 TTF 字體;檢查 imagettftext 返回值 |
| 內存洩漏 | 必須調用 imagedestroy();大並發下考慮緩存生成的圖片 |
composer require gregwar/captcha