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

PHP 實現中文驗證碼(基於 GD 库 + TTF 字體)

     編輯:PHP 相關知識

傳統英數驗證碼易被 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);

部署要點

  1. 字體檔案:需將 msyhbd.ttf(或任意支援中文的 TTF)放置於腳本同目錄,或指定絕對路徑。Linux 伺服器可用 wqy-zenhei.ttc(文泉驛正黑)。
  2. Session 儲存:實際使用時,將生成的 4 字驗證碼存入 `$_SESSION['captcha']`,驗證時比對(忽略大小寫)。
  3. 干擾元素:可在循環前加入噪點、干擾線:
    // 噪點
    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)));
    }
  4. 無障礙備選:提供音頻驗證碼或「換一張」按鈕,照顧視障用戶。

進階:驗證碼類別封裝

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)構建多層防禦體系。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved