本文提供兩種高安全性驗證碼的完整可執行程式碼:算術驗證碼(支援多題型)與 中文漢字驗證碼(TrueType 字體渲染),均含 Session 管理與干擾元素繪製。
<?php
session_start();
header("Content-Type: image/png");
// 1. 產生隨機運算元與運算子
$num1 = mt_rand(0, 9);
$num2 = mt_rand(1, 9); // 避免除以零
$operators = '+-*';
$operator = $operators[mt_rand(0, 2)];
// 2. 隨機選擇三種題型之一
$mode = mt_rand(1, 3);
$answer = 0;
switch ($mode) {
case 1: // 模式:A op B = ?
$code = "{$num1}{$operator}{$num2}=?";
eval("\$answer = {$num1}{$operator}{$num2};");
$_SESSION['captcha_answer'] = $answer;
break;
case 2: // 模式:A op _ = 結果(求 B)
eval("\$answer = {$num1}{$operator}{$num2};");
$code = "{$num1}{$operator}_={$answer}";
$_SESSION['captcha_answer'] = $num2;
break;
case 3: // 模式:_ op B = 結果(求 A)
eval("\$answer = {$num1}{$operator}{$num2};");
$code = "_{$operator}{$num2}={$answer}";
$_SESSION['captcha_answer'] = $num1;
break;
}
// 3. 建立圖片畫布
$width = 68;
$height = 28;
$img = imagecreate($width, $height);
// 4. 分配顏色
$colors = [
'bg' => imagecolorallocate($img, 255, 255, 255), // 白底
'text' => imagecolorallocate($img, 0, 0, 0), // 黑字
'gray' => imagecolorallocate($img, 200, 200, 200), // 灰色干擾
'red' => imagecolorallocate($img, 255, 0, 0), // 紅色干擾
];
// 5. 填充背景與繪製文字
imagefill($img, 0, 0, $colors['bg']);
imagestring($img, 5, 10, 8, $code, $colors['text']);
// 6. 加入干擾像素(噪點)
for ($i = 0; $i < 70; $i++) {
imagesetpixel($img, mt_rand(0, $width-10), mt_rand(0, $height-1), $colors['text']);
imagesetpixel($img, mt_rand(0, $width-10), mt_rand(0, $height-1), $colors['red']);
imagesetpixel($img, mt_rand(0, $width-10), mt_rand(0, $height-1), $colors['gray']);
}
// 7. 輸出並銷毀
imagepng($img);
imagedestroy($img);
?>
<?php
session_start();
header("Content-Type: image/png");
// 1. 漢字字庫(建議擴充至 2000+ 常用字)
$charset = "的一是在了不和有大這主中人上為們地個用工時要動國產以我到他會作來分生對於學下級就年階義發成部民可出能方進同行面說種過命度革而多子後自社加小機也經力線本電高量長黨得實家定深法表著水理化爭現所二起政三好十戰無農使性前等反體合斗路圖把結第裡正新開論之物從當兩些還天資事隊批如應形想制心樣干都向變關點育重其思與間內去因件日利相由壓員氣業代全組數果期導平各基或月毛然問比展那它最及外沒看治提五解系林者米群頭意只明四道馬認次文通但條較克又公孔領軍流入接席位情運器並飛原油放立題質指建區驗活眾很教決特此常石強極土少已根共直團統式轉別造切九你取西持總料連任志觀調七麼山程百報更見必真保熱委手改管處己將修支識病象幾先老光專什六型具示復安帶每東增則完風回南廣勞輪科北打積車計給節做務被整聯步類集號列溫裝即毫知軸研單色堅據速防史拉世設達爾場織歷花受求傳口斷況采精金界品判參層止邊清至萬確究書術狀廠須離再目海交權且兒青才證低越際八試規斯近注辦布門鐵需走議縣兵固除般引齒千勝細影濟白格效置推空配刀葉率述今選養德話查差半敵始片施響收華覺備名紅續均藥標記難存測士身緊液派准斤角降維板許破述技消底床田勢端感往神便賀村構照容非搞亞磨族火段算適講按值美態黃易彪服早班麥削信排台聲該擊素張密害侯草何樹肥繼右屬市嚴徑螺檢左頁抗蘇顯苦英快稱壞移約巴材省黑武培著河帝僅針怎植京助升王眼她抓含苗副雜普談圍食射源例致酸舊卻充足短劃劑宣環落首尺波承粉踐府魚隨考刻靠夠滿夫失包住促枝局菌桿周護巖師舉曲春元超負砂封換太模貧減陽揚江析畝木言球朝醫校古呢稻宋聽唯輸滑站另衛字鼓剛寫劉微略范供阿塊某功套友限項余倒卷創律雨讓骨遠幫初皮播優占死毒圈偉季訓控激找叫雲互跟裂糧粒母練塞鋼頂策雙留誤礎吸阻故寸盾晚絲女散焊功株親院冷徹彈錯散商視藝滅版烈零室輕血倍缺厘泵察絕富城沖噴壤簡否柱李望盤磁雄似困鞏益洲脫投送奴側潤蓋揮距觸星松送獲興獨官混紀依未突架寬冬章濕偏紋吃執閥礦寨責熟穩奪硬價努翻奇甲預職評讀背協損棉侵灰雖矛厚羅泥辟告卵箱掌氧恩愛停曾溶營終綱孟錢待盡俄縮沙退陳討奮械載胞幼哪剝迫旋征槽倒握擔仍呀鮮吧卡粗介鑽逐弱腳怕鹽末陰豐編印蜂急拿擴傷飛露核緣游振操央伍域甚迅輝異序免紙夜鄉久隸缸夾念蘭映溝乙嗎儒殺汽磷艱晶插埃燃歡鐵補咱芽永瓦傾陣碳演威附牙芽永瓦斜灌歐獻順豬洋腐請透司危括脈宜笑若尾束壯暴企菜穗楚漢愈綠拖牛份染既秋遍鍛玉夏療尖殖井費州訪吹榮銅沿替滾客召旱悟刺腦措貫藏敢令隙爐殼硫煤迎鑄粘探臨薄旬善福縱擇禮願伏殘雷延煙句純漸耕跑澤慢栽魯赤繁境潮橫掉錐希池敗船假亮謂托伙哲懷割擺貢呈勁財儀沉煉麻罪祖息車穿貨銷齊鼠抽畫飼龍庫守築房歌寒喜哥洗蝕廢納腹乎錄鏡婦惡脂莊擦險贊鐘搖典柄辯竹谷賣亂虛橋奧伯趕垂途額壁網截野遺靜謀弄掛課鎮妄盛耐援扎慮鍵歸符慶聚繞摩忙舞遇索顧膠羊湖釘仁音跡碎伸燈避泛亡答勇頻皇柳哈揭甘諾概憲濃島襲誰洪謝炮澆斑訊懂靈蛋閉孩釋乳巨徒私銀伊景坦累勻霉杜樂勒隔彎績招紹胡呼痛峰零柴簧午跳居尚丁秦稍追梁折耗鹼殊崗挖氏刃劇堆赫荷胸衡勤膜篇登駐案刊秧緩凸役剪川雪鏈漁啦臉戶洛孢勃盟買楊宗焦賽旗濾硅炭股坐蒸凝竟陷槍黎救冒暗洞犯筒您宋弧爆謬塗味津臂障褐陸啊健尊豆拔莫抵桑坡縫警挑污冰柬嘴啥飯塑寄趙喊墊康遵牧遭幅園腔訂香肉弟屋敏恢忘衣孫齡嶺騙休借丹渡耳刨虎筆稀昆浪薩茶滴淺擁穴覆倫娘噸浸袖珠雌媽紫戲塔錘震歲貌潔剖牢鋒疑霸閃埔猛訴刷狠忽災鬧喬唐漏聞沈熔氯荒莖男凡搶像漿旁玻亦忠唱蒙予紛捕鎖尤乘烏智淡允叛畜俘摸銹掃畢璃寶芯爺鑒秘淨蔣鈣肩騰枯拋軌堂拌爸循誘祝勵肯酒繩窮塘燥泡袋朗喂鋁軟渠顆慣貿糞綜牆趨彼屆墨礙啟逆卸航霧冠丙街萊貝輻腸付吉滲瑞驚頓擠秒懸姆爛森糖聖凹陶詞遲蠶億矩";
$charLen = mb_strlen($charset, 'UTF-8');
$selected = [];
// 2. 隨機選取 4 個漢字
for ($i = 0; $i < 4; $i++) {
$pos = mt_rand(0, $charLen - 1);
$selected[] = mb_substr($charset, $pos, 1, 'UTF-8');
}
$captchaCode = implode('', $selected);
$_SESSION['captcha_answer'] = $captchaCode;
// 3. 建立較大畫布(漢字需更多空間)
$width = 130;
$height = 50;
$img = imagecreate($width, $height);
// 4. 顏色分配
$bgColor = imagecolorallocate($img, 255, 255, 255);
$fontColor = imagecolorallocate($img, 0, 0, 0);
$lineColor = imagecolorallocate($img, 200, 180, 160);
// 5. 字體檔案(需自行下載 simhei.ttf 放置同目錄)
$fontFile = __DIR__ . '/simhei.ttf';
if (!file_exists($fontFile)) {
// 降級方案:使用內建字體(不支援中文)
imagestring($img, 5, 10, 15, 'FONT MISSING', $fontColor);
imagepng($img);
imagedestroy($img);
exit;
}
// 6. 繪製干擾線條
for ($i = 0; $i < 10; $i++) {
imageline($img,
mt_rand(0, $width), mt_rand(0, $height),
mt_rand(0, $width), mt_rand(0, $height),
imagecolorallocate($img, mt_rand(150,255), mt_rand(150,255), mt_rand(150,255))
);
}
// 7. 繪製漢字(隨機大小、角度、位置)
for ($i = 0; $i < 4; $i++) {
$x = ($width / 4) * $i + mt_rand(5, 15);
$y = mt_rand($height/2 + 5, $height - 5);
$size = mt_rand(18, 22);
$angle = mt_rand(-15, 15);
imagettftext($img, $size, $angle, $x, $y, $fontColor, $fontFile, $selected[$i]);
}
// 8. 輸出
imagepng($img);
imagedestroy($img);
?>
<?php
session_start();
?>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>驗證碼測試</title>
</head>
<body>
<form method="POST" action="">
<p>
算術驗證碼:<br>
<img src="math_captcha.php" id="mathCaptcha" style="vertical-align:middle; cursor:pointer" title="點擊更換">
<input type="text" name="math_answer" required>
</p>
<p>
漢字驗證碼:<br>
<img src="chinese_captcha.php" id="chineseCaptcha" style="vertical-align:middle; cursor:pointer" title="點擊更換">
<input type="text" name="chinese_answer" required>
</p>
<button type="submit">提交驗證</button>
</form>
<script>
// 點擊圖片重新整理驗證碼
document.getElementById('mathCaptcha').onclick = function() {
this.src = 'math_captcha.php?' + Date.now();
};
document.getElementById('chineseCaptcha').onclick = function() {
this.src = 'chinese_captcha.php?' + Date.now();
};
</script>
</body>
</html>
<?php
// 後端驗證邏輯
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$mathOk = isset($_SESSION['captcha_answer']) && $_POST['math_answer'] == $_SESSION['captcha_answer'];
// 注意:此處為示範,實際應分開兩個 Session 鍵名
echo $mathOk ? "✅ 算術驗證通過" : "❌ 算術驗證失敗";
}
?>
<img src="captcha.php"> 在主頁面中嵌入,兩者共享同一 Session ID。
imagettftext 的旋轉參數,或實作彎曲文字(需 GD 進階)算術驗證碼適合國際化場景,漢字驗證碼在中文環境具最高安全性。根據業務需求選擇或混合部署,並持續迭代干擾策略,對抗日益進化的 OCR 識別技術。