驗證碼是防禦機器人惡意註冊、暴力破解的基礎防線。本文從零建立一個數字圖形驗證碼系統,涵蓋:GD 繪圖干擾線/噪點、Session 儲存驗證值、前端表單整合、後端驗證邏輯與安全強化。
建立 captcha.php:
<?php
session_start();
// 1. 產生 4 位隨機數字
$code = '';
for ($i = 0; $i < 4; $i++) $code .= mt_rand(0, 9);
// 或直接:$code = (string)mt_rand(1000, 9999);
// 2. 存入 Session 供後續驗證
$_SESSION['captcha_code'] = $code;
// 3. 建立畫布
$width = 100; $height = 36;
$im = imagecreatetruecolor($width, $height);
// 4. 分配顏色
$bg = imagecolorallocate($im, 230, 230, 230); // 淺灰背景
$textColor = imagecolorallocate($im, 0, 0, 0); // 黑色文字
$noiseColor = imagecolorallocate($im, 150, 150, 150);
// 5. 填充背景
imagefill($im, 0, 0, $bg);
// 6. 繪製干擾線 (3 條)
for ($i = 0; $i < 3; $i++) {
imageline($im,
mt_rand(0, $width), mt_rand(0, $height),
mt_rand(0, $width), mt_rand(0, $height),
$noiseColor
);
}
// 7. 繪製干擾點 (50 個)
for ($i = 0; $i < 50; $i++) {
imagesetpixel($im, mt_rand(0, $width), mt_rand(0, $height), $noiseColor);
}
// 8. 繪製驗證碼文字 (逐字隨機位置)
$fontSize = 5; // 內建字體 1-5
$x = 10;
for ($i = 0; $i < 4; $i++) {
$y = mt_rand(4, 12);
imagestring($im, $fontSize, $x, $y, $code[$i], $textColor);
$x += mt_rand(18, 24); // 字元間距隨機
}
// 9. 輸出圖片
header('Content-Type: image/png');
imagepng($im);
imagedestroy($im);
?>
<form action="register.php" method="post">
<!-- 其他欄位 -->
<div>
<label>驗證碼:</label>
<input type="text" name="captcha" maxlength="4" required style="width: 80px;">
<img id="captchaImg" src="captcha.php" alt="點擊更換" style="vertical-align: middle; cursor: pointer;" title="點擊更換">
</div>
<button type="submit">註冊</button>
</form>
<script>
// 點擊圖片更換驗證碼
document.getElementById('captchaImg').onclick = function() {
this.src = 'captcha.php?' + Date.now(); // 防快取
};
</script>
register.php:
<?php
session_start();
// 1. 基本檢查
if (empty($_POST['captcha'])) {
exit(json_encode(['ok' => false, 'msg' => '請輸入驗證碼']));
}
// 2. 驗證碼比對 (不區分大小寫,數字無影響)
if (strtolower($_POST['captcha']) !== strtolower($_SESSION['captcha_code'] ?? '')) {
// 驗證失敗後清除舊碼,防止重試
unset($_SESSION['captcha_code']);
exit(json_encode(['ok' => false, 'msg' => '驗證碼錯誤']));
}
// 3. 驗證通過,清除 Session 碼 (一次性使用)
unset($_SESSION['captcha_code']);
// 4. 後續處理註冊邏輯...
// $username = $_POST['username']; ...
// 執行資料庫插入...
echo json_encode(['ok' => true, 'msg' => '註冊成功']);
?>
imagettftext() 搭配扭曲、旋轉,大幅提高機器識別難度。captcha.php 無任何輸出 (含空白行、BOM) 在 header() 之前,且檔案編碼為 UTF-8 無 BOM。session_start(),且 session.cookie_domain 設定正確。php -m | grep gd 檢查,或 phpinfo() 確認。