驗證碼是表單防刷、防機器人註冊的基礎元件。本文推薦一款經過實戰驗證的 PHP 數字驗證碼程式,具備干擾線、隨機噪點、字符隨機位置偏移等反辨識機制,程式碼結構清晰,支援 PHP 5.0+ 且需啟用 GD2 擴充套件,可直接整合至現有專案。
<?php
/**
* 檔案: showimg.php
* 用途: 數字驗證碼圖片生成
* 環境: PHP 5.0+、GD2 擴充套件 (php_gd2.dll)
* 作者: 17php.com
* 日期: 2007.03 (本文已優化重構)
*/
// 1. 生成 4 位隨機數字
$num = '';
for ($i = 0; $i < 4; $i++) {
$num .= rand(0, 9);
}
// 替代寫法: $num = sprintf('%04d', rand(1000, 9999)); // 確保 4 位數
// 2. 寫入 Session (驗證時使用)
session_start();
$_SESSION['Checknum'] = $num;
// 3. 設定圖片輸出標頭
header("Content-type: image/png");
header("Cache-Control: no-store, no-cache, must-revalidate, max-age=0");
header("Cache-Control: post-check=0, pre-check=0", false);
header("Pragma: no-cache");
// 4. 建立畫布與顏色
$im = imagecreate(60, 20); // 寬 60、高 20 像素
$black = imagecolorallocate($im, 0, 0, 0); // 黑色 (文字/干擾用)
$gray = imagecolorallocate($im, 200, 200, 200); // 淺灰色 (背景用)
imagefill($im, 0, 0, $gray); // 填充背景
// 5. 繪製 2 條隨機虛線干擾
$style = array($black, $black, $black, $black, $black, $gray, $gray, $gray, $gray, $gray);
imagesetstyle($im, $style);
$y1 = rand(0, 20); $y2 = rand(0, 20);
$y3 = rand(0, 20); $y4 = rand(0, 20);
imageline($im, 0, $y1, 60, $y3, IMG_COLOR_STYLED);
imageline($im, 0, $y2, 60, $y4, IMG_COLOR_STYLED);
// 6. 繪製 80 個隨機黑點噪點
for ($i = 0; $i < 80; $i++) {
imagesetpixel($im, rand(0, 60), rand(0, 20), $black);
}
// 7. 繪製 4 個數字:隨機水平起始位置 + 隨機間距 + 隨機垂直位置
$strx = rand(3, 8); // 起始 X 座標
for ($i = 0; $i < 4; $i++) {
$strpos = rand(1, 6); // 隨機 Y 座標
imagestring($im, 5, $strx, $strpos, substr($num, $i, 1), $black);
$strx += rand(8, 12); // 下一個字符 X 座標隨機偏移 8-12 像素
}
// 8. 輸出並釋放資源
imagepng($im);
imagedestroy($im);
?>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>驗證碼測試頁面</title>
<style>
.captcha-img { vertical-align: middle; cursor: pointer; border: 1px solid #ddd; }
.captcha-input { width: 80px; padding: 5px; font-size: 16px; }
</style>
</head>
<body>
<form action="verify.php" method="post">
<label>請輸入驗證碼:
<input type="text" name="passcode" class="captcha-input" maxlength="4" required>
<img id="captchaImg" class="captcha-img" src="showimg.php" alt="驗證碼" title="點擊更換">
</label>
<br><br>
<button type="submit">提交驗證</button>
</form>
<script>
// 點擊圖片更換驗證碼 (防快取參數)
document.getElementById('captchaImg').addEventListener('click', function() {
this.src = 'showimg.php?' + Date.now();
});
</script>
</body>
</html>
<?php
session_start();
$code = $_POST['passcode'] ?? '';
$validCode = $_SESSION['Checknum'] ?? '';
// 驗證邏輯:不分大小寫比對 (數字無大小寫,但保留良好習慣)
if (strcasecmp($code, $validCode) === 0) {
echo '<div style="color:green; font-weight:bold;">✅ 驗證通過!歡迎進入系統。</div>';
// 這裡執行後續業務邏輯 (登入、註冊、提交表單等)
// 驗證成功後建議銷毀驗證碼,防止重複使用
unset($_SESSION['Checknum']);
} else {
echo '<div style="color:red; font-weight:bold;">❌ 驗證碼錯誤,請重新輸入。</div>';
}
?>
rand() 替換為 random_int() (PHP 7+) 或 openssl_random_pseudo_bytes(),提升熵值。imagettftext() 搭配 .ttf 字體,可實現字體旋轉、扭曲、陰影等更強干擾效果。'ABCDEFGHJKLMNPQRSTUVWXYZ23456789' (排除易混淆字符 O/0, I/1)。| 現象 | 可能原因 | 解決方案 |
|---|---|---|
| 圖片顯示為破圖/無輸出 | GD2 未啟用或 PHP 錯誤輸出干擾圖片標頭 | 檢查 php.ini 啟用 extension=gd2;確保圖片輸出前無任何 echo/空白/錯誤訊息 |
| 驗證永遠失敗 | Session 未啟動/路徑錯誤/驗證碼已被銷毀 | 所有檔案最開頭呼叫 session_start();檢查 session.save_path 可寫入 |
| 中文亂碼 | 檔案編碼非 UTF-8 或字體不支援中文 | 檔案存為 UTF-8 無 BOM;使用支援中文的 .ttf 字體 |
本文提供的驗證碼程式碼功能完整、邏輯清晰,涵蓋生成、顯示、驗證全流程。開發者可直接複製 showimg.php 使用,並根據專案需求調整圖片尺寸、字符集、干擾強度。記住:驗證碼只是第一道防線,配合限制提交頻率、IP 封鎖、行為分析 (如 reCAPTCHA v3)、雙因子認證 (2FA) 等措施,才能構建完整的帳號安全體系。