傳統亂碼驗證碼使用者體驗差,單字驗證碼優勢明顯:
words.txt:每行一個單字,建議 5,000+ 詞彙,長度 4-8 字元
apple banana computer developer elephant ...
function vcaptcha_read_code($wordlist_file) {
$fp = @fopen($wordlist_file, 'rb');
if (!$fp) return false;
$fsize = filesize($wordlist_file);
if ($fsize < 32) return false;
// 讀取隨機 128 位元組區塊 (避免載入整個大檔)
$max = min(128, $fsize);
fseek($fp, mt_rand(0, $fsize - $max), SEEK_SET);
$data = fread($fp, 128);
fclose($fp);
// 正規化換行符
$data = preg_replace("/\r?\n/", "\n", $data);
// 隨機起始位置 (前 100 字元內找換行)
$start = strpos($data, "\n", mt_rand(0, min(100, strlen($data)-1))) + 1;
// 找結束換行
$end = strpos($data, "\n", $start);
return strtolower(substr($data, $start, $end - $start));
}
**關鍵優化**:不載入整個詞庫至記憶體,適合大型詞庫檔案。
$width = 145; $height = 45;
$authcode = vcaptcha_read_code('words.txt');
$letters = strlen($authcode);
$bg = 'bg/captcha_bg3.jpg';
$img_bg = imagecreatefromjpeg($bg);
$bg_width = imagesx($img_bg); $bg_height = imagesy($img_bg);
$img_org = imagecreatetruecolor($width, $height);
// 縮放背景至目標尺寸
imagecopyresampled($img_org, $img_bg, 0, 0, 0, 0, $width, $height, $bg_width, $bg_height);
imagedestroy($img_bg);
$white = imagecolorallocate($img_org, 255, 255, 255);
imagerectangle($img_org, 0, 0, $width-1, $height-1, $white); // 邊框
// 置中繪製文字
$x = ($width - imagefontwidth(5) * $letters) / 2;
$y = ($height - imagefontheight(5)) / 2;
imagestring($img_org, 5, $x, $y, $authcode, $white);
// 輸出
header('Content-Type: image/png');
imagepng($img_org);
imagedestroy($img_org);
<img id="captcha_img" title="點擊更換驗證碼"
src="captcha_word.php" onclick="refreshCaptcha()" />
<script>
function refreshCaptcha() {
const img = document.getElementById('captcha_img');
img.src = 'captcha_word.php?' + Math.random(); // 破解快取
}
</script>
imagettftext() + TTF 字體,支援反鋸齒、旋傾、字間距單字驗證碼在安全性與使用體驗間取得良好平衡,配合詞庫豐富度與圖片干擾強度,可有效抵禦自動化攻擊並保持使用者友善度。