GD 的 imagettftext() 僅支援 UTF-8 編碼字串,因此生成中文驗證碼時,必須將原始碼(通常為 UTF-8)或資料庫讀出的字串確認為 UTF-8,若來源為 GB2312/Big5 需先 iconv() 或 mb_convert_encoding() 轉碼。本文提供三種不同複雜度的實作,涵蓋基本干擾、多字隨機、Session 驗證流程。
<?php
session_start();
header("Content-Type: image/png");
// 1. 字串池(需為 UTF-8 編碼儲存)
$ch_str = "駕駛飛機大砲坦克戰艦潛艇火箭導彈";
$chars = [];
for ($i = 0; $i < mb_strlen($ch_str, 'UTF-8'); $i++) {
$chars[] = mb_substr($ch_str, $i, 1, 'UTF-8');
}
// 2. 畫布設定
$w = 200; $h = 100;
$im = imagecreatetruecolor($w, $h);
$bg = imagecolorallocate($im, 255, 255, 255);
imagefill($im, 0, 0, $bg);
// 3. 干擾元素
$font = __DIR__ . '/fonts/simfang.ttf'; // 需自備 TTF
$noiseColor = imagecolorallocate($im, 0, 0, 0);
for ($i = 0; $i < 3000; $i++) {
imagesetpixel($im, mt_rand(0, $w), mt_rand(0, $h), $noiseColor);
}
$lineColor = imagecolorallocate($im, 0xAA, 0xAA, 0xAA);
for ($i = 0; $i < 80; $i++) {
imageline($im, mt_rand(0, $w), mt_rand(0, $h), mt_rand(0, $w), mt_rand(0, $h), $lineColor);
}
// 4. 隨機抽 2 字並繪製
$code = '';
for ($i = 0; $i < 2; $i++) {
$c = $chars[array_rand($chars)];
$code .= $c;
$color = imagecolorallocate($im, mt_rand(0, 100), mt_rand(0, 150), mt_rand(0, 200));
$size = mt_rand(28, 32);
$angle = mt_rand(-15, 15);
$x = ($w / 4) * $i + mt_rand(20, 40);
$y = $h / 2 + mt_rand(10, 20);
imagettftext($im, $size, $angle, $x, $y, $color, $font, $c);
}
$_SESSION['captcha'] = $code; // 存入 Session 驗證用
imagepng($im);
imagedestroy($im);
?>
<?php
$str = "中文漢字"; // 假設來源為 GB2312 編碼檔案
$str_utf8 = iconv("GB2312", "UTF-8", $str); // 轉為 UTF-8
// 後續直接用 $str_utf8 傳給 imagettftext()
?>
<?php
// captcha.php
session_start();
class Captcha {
private $im, $code;
public function __construct($len = 4, $w = 130, $h = 40) {
$this->im = imagecreatetruecolor($w, $h);
$this->generate($len);
}
private function generate($len) {
$pool = 'ABCDEFGHJKLMNPQRSTUVWXYZ23456789'; // 避免易混淆字元
$this->code = '';
for ($i = 0; $i < $len; $i++) {
$this->code .= $pool[mt_rand(0, strlen($pool)-1)];
}
$_SESSION['captcha_code'] = strtolower($this->code);
// 背景、干擾、繪製文字...(略,同方案一)
// 最後輸出
header("Content-Type: image/png");
imagepng($this->im);
imagedestroy($this->im);
}
public static function verify($input) {
return strtolower(trim($input)) === ($_SESSION['captcha_code'] ?? '');
}
}
new Captcha(); // 直接輸出圖片
?>
<img id="captchaImg" src="captcha.php" alt="驗證碼" style="cursor:pointer;" onclick="this.src='captcha.php?'+Date.now()"> <input type="text" name="captcha" placeholder="輸入驗證碼">
<?php
session_start();
if (Captcha::verify($_POST['captcha'])) {
echo "驗證通過";
} else {
echo "驗證碼錯誤";
}
?>
php-gd 且支援 FreeType(php -i | grep -i freetype)。simfang.ttf, msjh.ttc)放置於可讀取路徑,並確認路徑正確。session.save_path)。