首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

PHP 中文驗證碼生成三法:TTF 字體、干擾線、Session 驗證完整實作

     編輯:PHP 相關知識

中文驗證碼的特殊挑戰與解決方案

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);
?>

方案二:iconv 轉碼範例(GB2312 → UTF-8)

<?php
$str = "中文漢字"; // 假設來源為 GB2312 編碼檔案
$str_utf8 = iconv("GB2312", "UTF-8", $str); // 轉為 UTF-8
// 後續直接用 $str_utf8 傳給 imagettftext()
?>

方案三:完整驗證碼類(含 Session 驗證、點擊換圖)

<?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)。
  • TTF 字體檔(如 simfang.ttf, msjh.ttc)放置於可讀取路徑,並確認路徑正確。
  • Session 儲存目錄可寫入(session.save_path)。
  • 生產環境建議加入 Rate Limiting 防止暴力刷新驗證碼圖片。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved