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

PHP 封裝驗證碼類完整實作與使用教學

     編輯:PHP 綜合知識

類別功能特色

  • 可配置寬高、字元數、干擾點/弧線密度
  • 支援內建字型 (imagechar) 與 TrueType 字型 (imagettftext)
  • 自動計算干擾元素數量,平衡可讀性與安全性
  • 提供 showImage() 直接輸出圖片、getCheckCode() 取得驗證碼字串
  • 解構子自動釋放 GD 資源

完整類別程式碼

<?php
class ValidationCode {
    private $width;
    private $height;
    private $codeNum;
    private $image;
    private $disturbColorNum;
    private $checkCode;

    public function __construct($width = 80, $height = 20, $codeNum = 4) {
        $this->width = $width;
        $this->height = $height;
        $this->codeNum = $codeNum;
        $this->checkCode = $this->createCheckCode();

        $number = floor($width * $height / 15);
        $this->disturbColorNum = ($number > 240 - $codeNum) ? 240 - $codeNum : $number;
    }

    // 公開介面:輸出驗證碼圖片至瀏覽器
    public function showImage($fontFace = "") {
        $this->createImage();
        $this->setDisturbColor();
        $this->outputText($fontFace);
        $this->outputImage();
    }

    // 公開介面:取得驗證碼字串 (供 Session 儲存比對)
    public function getCheckCode() {
        return $this->checkCode;
    }

    private function createImage() {
        $this->image = imagecreatetruecolor($this->width, $this->height);
        $backColor = imagecolorallocate($this->image, rand(225, 255), rand(225, 255), rand(225, 255));
        imagefill($this->image, 0, 0, $backColor);
        $border = imagecolorallocate($this->image, 0, 0, 0);
        imagerectangle($this->image, 0, 0, $this->width - 1, $this->height - 1, $border);
    }

    private function setDisturbColor() {
        // 噪點
        for ($i = 0; $i < $this->disturbColorNum; $i++) {
            $color = imagecolorallocate($this->image, rand(0, 255), rand(0, 255), rand(0, 255));
            imagesetpixel($this->image, rand(1, $this->width - 2), rand(1, $this->height - 2), $color);
        }
        // 干擾弧線
        for ($i = 0; $i < 10; $i++) {
            $color = imagecolorallocate($this->image, rand(200, 255), rand(200, 255), rand(200, 255));
            imagearc($this->image, rand(-10, $this->width), rand(-10, $this->height), rand(30, 300), rand(20, 200), 55, 44, $color);
        }
    }

    private function createCheckCode() {
        $code = "23456789abcdefghijkmnpqrstuvwxyzABCDEFGHIJKMNPQRSTUVWXYZ"; // 排除易混淆 0,O,1,l,I
        $string = '';
        for ($i = 0; $i < $this->codeNum; $i++) {
            $string .= $code[rand(0, strlen($code) - 1)];
        }
        return $string;
    }

    private function outputText($fontFace = "") {
        for ($i = 0; $i < $this->codeNum; $i++) {
            $fontcolor = imagecolorallocate($this->image, rand(0, 128), rand(0, 128), rand(0, 128));
            if ($fontFace == "") {
                $fontsize = rand(3, 5);
                $x = floor($this->width / $this->codeNum) * $i + 3;
                $y = rand(0, $this->height - 15);
                imagechar($this->image, $fontsize, $x, $y, $this->checkCode[$i], $fontcolor);
            } else {
                $fontsize = rand(12, 16);
                $x = floor(($this->width - 8) / $this->codeNum) * $i + 8;
                $y = rand($fontsize + 5, $this->height);
                imagettftext($this->image, $fontsize, rand(-30, 30), $x, $y, $fontcolor, $fontFace, $this->checkCode[$i]);
            }
        }
    }

    private function outputImage() {
        if (imagetypes() & IMG_GIF) {
            header("Content-Type: image/gif");
            imagegif($this->image);
        } elseif (imagetypes() & IMG_JPG) {
            header("Content-Type: image/jpeg");
            imagejpeg($this->image);
        } elseif (imagetypes() & IMG_PNG) {
            header("Content-Type: image/png");
            imagepng($this->image);
        } elseif (imagetypes() & IMG_WBMP) {
            header("Content-Type: image/vnd.wap.wbmp");
            imagewbmp($this->image);
        } else {
            die("PHP 不支援圖像創建");
        }
    }

    public function __destruct() {
        if ($this->image) imagedestroy($this->image);
    }
}
?>

使用範例

code.php (驗證碼圖片輸出入口)

<?php
session_start();
require_once "validationcode.class.php";

$code = new ValidationCode(100, 30, 4); // 寬100 高30 4位字元
$code->showImage(); // 直接輸出圖片二進位
$_SESSION["verify_code"] = $code->getCheckCode(); // 儲存至 Session
?>

HTML 表單引用

<img src="code.php" id="captcha" onclick="this.src='code.php?'+Math.random()" style="cursor:pointer">
<input type="text" name="verify" placeholder="輸入驗證碼">

驗證邏輯

<?php
session_start();
if (strtoupper($_POST['verify']) === strtoupper($_SESSION['verify_code'])) {
    echo "驗證通過";
} else {
    echo "驗證碼錯誤";
}
?>

進階優化建議

  • 字型檔案:準備多款 TTF 字體隨機切換,增加識別難度。
  • Session 安全:驗證成功後立即 unset($_SESSION['verify_code']) 防止重複使用。
  • 無障礙:提供語音驗證碼或點選式驗證替代方案。
  • 效能:高流量建議改用 imagepng 並啟用 HTTP 快取頭,或前端改用 JavaScript 生成 (如 Canvas)。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved