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

PHP 驗證碼(CAPTCHA)完整實現:GD 庫繪製、Session 驗證與前端刷新

     編輯:PHP 相關知識

從零構建安全可用的 PHP 驗證碼

驗證碼是防禦機器人註冊、暴力破解、垃圾評論的第一道防線。本文提供基於 GD 庫的完整類實現,涵蓋干擾點/線、字符隨機、Session 存儲、前端無刷新切換等生產級細節。

核心類實現(Vcode.php)

<?php
class Vcode {
    private int $width;
    private int $height;
    private int $codeNum;
    private int $pixNum;
    private int $lineNum;
    private string $checkCode = '';
    private $image;

    public function __construct(
        int $width = 120,
        int $height = 40,
        int $codeNum = 4,
        int $pixNum = 60,
        int $lineNum = 5
    ) {
        $this->width = $width;
        $this->height = $height;
        $this->codeNum = $codeNum;
        $this->pixNum = $pixNum;
        $this->lineNum = $lineNum;
    }

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

    private function createCode(): void {
        $chars = '3456789abcdefghijkmnpqrstuvwxyABCDEFGHIJKMNPQRSTUVWXY'; // 排除易混淆字符
        for ($i = 0; $i < $this->codeNum; $i++) {
            $char = $chars[random_int(0, strlen($chars) - 1)];
            $this->checkCode .= $char;
            $color = imagecolorallocate($this->image, random_int(0, 128), random_int(0, 128), random_int(0, 128));
            $size = random_int(16, 24); // 字體大小(需 TTF 支援更好)
            $x = random_int(5, $this->width - imagefontwidth($size) - 5);
            $y = random_int(5, $this->height - imagefontheight($size) - 5);
            imagestring($this->image, $size, $x, $y, $char, $color);
        }
    }

    private function setDisturb(): void {
        // 干擾點
        for ($i = 0; $i < $this->pixNum; $i++) {
            $color = imagecolorallocate($this->image, random_int(0, 255), random_int(0, 255), random_int(0, 255));
            imagesetpixel($this->image, random_int(1, $this->width - 2), random_int(1, $this->height - 2), $color);
        }
        // 干擾線
        for ($i = 0; $i < $this->lineNum; $i++) {
            $color = imagecolorallocate($this->image, random_int(0, 255), random_int(0, 255), random_int(0, 255));
            imageline($this->image,
                random_int(0, $this->width / 2), random_int(0, $this->height / 2),
                random_int($this->width / 2, $this->width), random_int($this->height / 2, $this->height),
                $color
            );
        }
    }

    public function output(): void {
        session_start();
        $_SESSION['captcha_code'] = strtoupper($this->checkCode);
        $this->createImage();
        $this->createCode();
        $this->setDisturb();
        header('Content-Type: image/png');
        imagepng($this->image);
        imagedestroy($this->image);
    }
}

入口腳本(captcha.php)

<?php
require_once 'Vcode.php';
$captcha = new Vcode();
$captcha->output();

前端整合(HTML + JS)

<img id="captchaImg" src="captcha.php" alt="驗證碼" style="cursor:pointer;vertical-align:middle">
<a href="javascript:void(0)" id="refreshCaptcha" style="margin-left:8px">看不清?換一張</a>
<input type="text" name="captcha" placeholder="請輸入驗證碼" required>

<script>
document.getElementById('captchaImg').addEventListener('click', refresh);
document.getElementById('refreshCaptcha').addEventListener('click', refresh);

function refresh() {
    const img = document.getElementById('captchaImg');
    img.src = 'captcha.php?' + Date.now(); // 時間戳防緩存
}
</script>

後端驗證邏輯

<?php
session_start();
$input = strtoupper(trim($_POST['captcha'] ?? ''));
$stored = $_SESSION['captcha_code'] ?? '';
unset($_SESSION['captcha_code']); // 一次性

if ($input !== $stored) {
    exit(json_encode(['code' => 400, 'msg' => '驗證碼錯誤']));
}
// 通過,繼續業務邏輯...

安全加固建議

  • 使用 TTF 字體 + imagettftext:支援傾斜、旋轉、字距隨機,大幅提高識別難度。
  • 限制請求頻率:同 IP 分鐘請求 < 10 次,防暴力刷圖。
  • 加入行為分析:滑塊、點選、無感驗證(Google reCAPTCHA v3 / Geetest)替代傳統圖形驗證碼。
  • HTTPS 傳輸:防止中間人竄改圖片/攔截 Session。
  • Session 安全:session.cookie_httponly=1、session.cookie_secure=1、session.use_strict_mode=1。

常見問題排查

現象原因解決
圖片顯示破損/空白腳本輸出了 BOM/空白/錯誤訊息確保 header() 前無任何輸出,檔案存 UTF-8 無 BOM
驗證總是失敗Session 未啟動/域名不匹配/大小寫兩端都 session_start(),統一 strtoupper 比對
字符重疊/超出邊界座標計算未考慮字體寬高用 imagefontwidth/height 或 imagettfbbox 精確計算
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved