傳統英數驗證碼易被 OCR 識別,中文驗證碼因字符集大、筆劃複雜,能有效提升機器識別難度。本文提供一個輕量級實現,直接輸出 PNG 圖片。
<?php
// 1. 字符庫:常用漢字 200 字(可自行擴充)
$text = '的一是不了能好都然沒日於起還發成事只作當想看文無開手十用主行方又如前所本見經頭面公同三已老從動兩長知民樣現分將外但身些與高意進把法此實回二理美點月明其種聲全工己話兒者向情部正名定女問力機給等幾很業最間新什打便位因重被走電四第門相次東政海口使教西再平真聽世氣信北少關並內加化由卻代軍產入先山五太水萬市眼體別處總才場師書比住員九笑性通目華報立馬命張活難神數件安表原車白應路期叫死常提感金何更反合放做系計或司利受光王果親界及今京務制解各任至清物台象記邊共風戰干接它許八特覺望直服毛林題建南度統色字請交愛讓';
// 2. 建立畫布
$im = imagecreatetruecolor(100, 45);
$font = __DIR__ . '/msyhbd.ttf'; // 微軟雅黑粗體,需自行放置字體檔案
// 3. 背景色(淺灰)
$grey = imagecolorallocate($im, 200, 200, 200);
imagefill($im, 0, 0, $grey);
// 4. 繪製 4 個隨機漢字
$len = mb_strlen($text, 'UTF-8');
for ($i = 0, $x = 0; $i < 4; $i++) {
// 隨機顏色(避免太淺)
$color = imagecolorallocate($im, mt_rand(0, 190), mt_rand(0, 190), mt_rand(0, 190));
// 隨機水平位移
$x += $i * 10 + mt_rand(1, 5);
// 取一個隨機漢字
$char = mb_substr($text, mt_rand(0, $len - 1), 1, 'UTF-8');
// 繪製:字體大小 10-16pt、旋轉 -15~15°、Y 軸 21-25px
imagettftext($im, mt_rand(10, 16), mt_rand(-15, 15), $x, mt_rand(21, 25), $color, $font, $char);
}
// 5. 輸出圖片
header('Content-Type: image/png');
imagepng($im);
imagedestroy($im);
msyhbd.ttf(或任意支援中文的 TTF)放置於腳本同目錄,或指定絕對路徑。Linux 伺服器可用 wqy-zenhei.ttc(文泉驛正黑)。// 噪點
for ($i = 0; $i < 200; $i++) {
imagesetpixel($im, mt_rand(0, 100), mt_rand(0, 45), imagecolorallocate($im, mt_rand(0,255), mt_rand(0,255), mt_rand(0,255)));
}
// 干擾線
for ($i = 0; $i < 5; $i++) {
imageline($im, mt_rand(0,100), mt_rand(0,45), mt_rand(0,100), mt_rand(0,45), imagecolorallocate($im, mt_rand(0,190), mt_rand(0,190), mt_rand(0,190)));
}
class ChineseCaptcha {
private $chars;
private $font;
private $width = 120;
private $height = 50;
private $count = 4;
public function __construct($fontPath, $chars = '') {
$this->font = $fontPath;
$this->chars = $chars ?: '的一是不了人我在有他這為之大來以個中們地也子曰生那些國年過發...'; // 續寫
}
public function generate() {
$im = imagecreatetruecolor($this->width, $this->height);
$bg = imagecolorallocate($im, 230, 230, 230);
imagefill($im, 0, 0, $bg);
$len = mb_strlen($this->chars, 'UTF-8');
$code = '';
for ($i = 0, $x = 10; $i < $this->count; $i++) {
$color = imagecolorallocate($im, mt_rand(0,150), mt_rand(0,150), mt_rand(0,150));
$char = mb_substr($this->chars, mt_rand(0, $len-1), 1, 'UTF-8');
$code .= $char;
$angle = mt_rand(-20, 20);
$y = mt_rand(25, 35);
imagettftext($im, mt_rand(18, 24), $angle, $x, $y, $color, $this->font, $char);
$x += mt_rand(22, 28);
}
// 加入干擾線/點...
return ['image' => $im, 'code' => $code];
}
public function output() {
$res = $this->generate();
header('Content-Type: image/png');
imagepng($res['image']);
imagedestroy($res['image']);
return $res['code'];
}
}
// 使用:
// $captcha = new ChineseCaptcha(__DIR__.'/msyhbd.ttf');
// $_SESSION['captcha'] = $captcha->output();
中文驗證碼雖提高識別門檻,但隨著深度學習 OCR 進步,建議結合行為分析(滑塊、點選、設備指紋)或第三方驗證服務(reCAPTCHA、Geetest)構建多層防禦體系。