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

PHP 生成可點擊刷新的驗證碼:GD 庫實現、AJAX 無刷新換圖

     編輯:PHP 綜合知識

核心文件結構

captcha/
├── index.html    # 演示頁
├── captcha.php   # 驗證碼圖片生成端點
└── check.php     # 驗證端點 (可選)

1. 驗證碼生成 (captcha.php)

<?php
// captcha.php
session_start();

// 配置
$width  = 100;
$height = 38;
$length = 4;              // 字符數
$charset = '23456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnpqrstuvwxyz'; // 去除易混淆 0/O/1/I/l

// 建立畫布
$img = imagecreatetruecolor($width, $height);
$bg = imagecolorallocate($img, 245, 245, 245); // 淺灰背景
imagefill($img, 0, 0, $bg);

// 干擾線
for ($i = 0; $i < 5; $i++) {
    $color = imagecolorallocate($img, mt_rand(150, 200), mt_rand(150, 200), mt_rand(150, 200));
    imageline($img, mt_rand(0, $width), mt_rand(0, $height), mt_rand(0, $width), mt_rand(0, $height), $color);
}

// 干擾點
for ($i = 0; $i < 50; $i++) {
    $color = imagecolorallocate($img, mt_rand(100, 200), mt_rand(100, 200), mt_rand(100, 200));
    imagesetpixel($img, mt_rand(0, $width), mt_rand(0, $height), $color);
}

// 繪製字符
$code = '';
for ($i = 0; $i < $length; $i++) {
    $char = $charset[mt_rand(0, strlen($charset) - 1)];
    $code .= $char;
    $x = 15 + $i * 20 + mt_rand(-2, 2);
    $y = mt_rand(6, 14);
    $angle = mt_rand(-15, 15);
    $color = imagecolorallocate($img, mt_rand(0, 80), mt_rand(0, 80), mt_rand(0, 80));
    // 使用 TTF 字體更美觀 (需字體文件)
    // imagettftext($img, 20, $angle, $x, $y, $color, __DIR__.'/font.ttf', $char);
    // 內置字體 fallback
    imagestring($img, 5, $x, $y, $char, $color);
}

$_SESSION['captcha_code'] = strtolower($code); // 不區分大小寫

// 輸出
header('Content-Type: image/png');
header('Cache-Control: no-store, no-cache, must-revalidate');
header('Pragma: no-cache');
imagepng($img);
imagedestroy($img);

2. 前端頁面 (index.html)

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>驗證碼演示</title>
    <style>
        .captcha-wrap { display: flex; align-items: center; gap: 10px; }
        .captcha-img { cursor: pointer; border: 1px solid #ddd; border-radius: 4px; }
        .refresh-btn { padding: 6px 12px; background: #007bff; color: #fff; border: none; border-radius: 4px; cursor: pointer; }
        .refresh-btn:hover { background: #0056b3; }
    </style>
</head>
<body>
    <h3>登入驗證碼</h3>
    <div class="captcha-wrap">
        <img id="captchaImg" class="captcha-img" src="captcha.php?t=" alt="驗證碼" title="點擊刷新">
        <button type="button" class="refresh-btn" id="refreshBtn">換一張</button>
    </div>
    <br><br>
    <input type="text" id="captchaInput" placeholder="輸入驗證碼" maxlength="4" style="text-transform:uppercase">
    <button onclick="verify()">提交驗證</button>
    <p id="msg"></p>

    <script>
        const img = document.getElementById('captchaImg');
        const btn = document.getElementById('refreshBtn');
        
        function refresh() {
            // 關鍵:加隨機參數避免瀏覽器緩存
            img.src = 'captcha.php?t=' + Date.now() + Math.random();
        }
        
        // 點擊圖片或按鈕刷新
        img.onclick = refresh;
        btn.onclick = refresh;
        
        async function verify() {
            const code = document.getElementById('captchaInput').value.trim();
            if (!code) return alert('請輸入驗證碼');
            
            const res = await fetch('check.php', {
                method: 'POST',
                headers: {'Content-Type': 'application/x-www-form-urlencoded'},
                body: 'code=' + encodeURIComponent(code)
            });
            const data = await res.json();
            document.getElementById('msg').innerHTML = data.ok 
                ? '✅ 驗證通過' 
                : '❌ ' + data.msg;
            if (!data.ok) refresh(); // 失敗自動刷新
        }
    </script>
</body>
</html>

3. 驗證端點 (check.php)

<?php
// check.php
session_start();
header('Content-Type: application/json');

$input = strtolower(trim($_POST['code'] ?? ''));
$stored = $_SESSION['captcha_code'] ?? '';

if (!$input) {
    echo json_encode(['ok' => false, 'msg' => '驗證碼不能為空']);
} elseif ($input === $stored) {
    unset($_SESSION['captcha_code']); // 一次性使用
    echo json_encode(['ok' => true]);
} else {
    echo json_encode(['ok' => false, 'msg' => '驗證碼錯誤']);
}

進階:算術/中文/點選/滑塊驗證碼

類型生成邏輯適用場景
算術$a=rand(1,20); $b=rand(1,20); $op=['+','-'][rand(0,1)]; $q="$a$op$b=?"; $_SESSION['captcha']=$a+$b*-1;低安全、趣味
中文字符集換成常用 500 漢字,TTF 必須支援中文國內用戶友好
點選生成 4-6 個隨機坐標,前端 Canvas 繪製,用戶按序點擊防機器識別強
滑塊前端 JS 拼圖邏輯,後端驗證軌跡/時間/誤差高安全、體驗好

安全加固清單

  • ✅ Session 存儲驗證碼 (而非 Cookie)
  • ✅ 一次性使用,驗證後立即 unset
  • ✅ 圖片響應頭禁用緩存
  • ✅ 字符集去除 0/O/1/I/l 等易混淆字符
  • ✅ 加入干擾線/點/扭曲/噪點
  • ⚠️ 生產環境建議接入 Google reCAPTCHA v3 / hCaptcha / GeeTest 等成熟方案

總結

核心三步:GD 繪圖 → Session 存儲 → 前端隨機參數防緩存刷新。本示例 50 行代碼實現完整閉環,可直接集成至登入/註冊/表單提交流程。

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