驗證碼用於區分人類與自動化腳本,保護登入、註冊、留言等表單免受暴力破解與垃圾內容攻擊。本文示範基於 GD 庫生成圖形驗證碼、Session 儲存、前端整合與驗證的完整流程。
captcha.php<?php
session_start();
// 1. 設定圖片尺寸
$width = 120; $height = 40;
$image = imagecreatetruecolor($width, $height);
// 2. 分配顏色
$bg = imagecolorallocate($image, 240, 240, 240); // 淺灰背景
$textColor = imagecolorallocate($image, 0, 0, 0);
$noiseColor = imagecolorallocate($image, 180, 180, 180);
// 3. 填充背景
imagefilledrectangle($image, 0, 0, $width, $height, $bg);
// 4. 產生隨機驗證碼 (4 位數字 + 字母)
$chars = '23456789ABCDEFGHJKLMNPQRSTUVWXYZ'; // 排除易混淆字元
$code = '';
for ($i = 0; $i < 4; $i++) {
$code .= $chars[mt_rand(0, strlen($chars) - 1)];
}
$_SESSION['captcha_code'] = $code; // 存入 Session
// 5. 繪製干擾線
for ($i = 0; $i < 5; $i++) {
imageline($image, mt_rand(0, $width), mt_rand(0, $height), mt_rand(0, $width), mt_rand(0, $height), $noiseColor);
}
// 6. 繪製干擾點
for ($i = 0; $i < 50; $i++) {
imagesetpixel($image, mt_rand(0, $width), mt_rand(0, $height), $noiseColor);
}
// 7. 繪製驗證碼文字 (隨機位置、旋轉、字體大小)
$fontSize = 20;
for ($i = 0; $i < 4; $i++) {
$x = 20 + $i * 24 + mt_rand(-3, 3);
$y = 28 + mt_rand(-3, 3);
$angle = mt_rand(-15, 15);
imagettftext($image, $fontSize, $angle, $x, $y, $textColor, __DIR__ . '/fonts/arial.ttf', $code[$i]);
}
// 8. 輸出 PNG
header('Content-Type: image/png');
imagepng($image);
imagedestroy($image);
?>
<form action="login_check.php" method="post">
<input type="text" name="username" placeholder="帳號" required>
<input type="password" name="password" placeholder="密碼" required>
<input type="text" name="captcha" placeholder="驗證碼" maxlength="4" required>
<img src="captcha.php" id="captchaImg" alt="驗證碼" style="vertical-align:middle; cursor:pointer;" title="點擊更換">
<button type="submit">登入</button>
</form>
<script>
document.getElementById('captchaImg').onclick = function() {
this.src = 'captcha.php?' + Date.now(); // 加時間戳防快取
};
</script>
login_check.php<?php
session_start();
$username = $_POST['username'] ?? '';
$password = $_POST['password'] ?? '';
$captcha = strtoupper($_POST['captcha'] ?? '');
if (empty($captcha) || $captcha !== $_SESSION['captcha_code']) {
// 驗證碼錯誤
$_SESSION['error'] = '驗證碼錯誤';
header('Location: login.php');
exit;
}
// 驗證碼正確,清除避免重複使用
unset($_SESSION['captcha_code']);
// 繼續帳號密碼驗證...
// $user = $db->findUser($username);
// if ($user && password_verify($password, $user['password_hash'])) { ... }
?>
imagecopyresampled 配合正弦波位移,或套用 imagick 的 distortImage。session_start() 必須在任何輸出前呼叫,且生成圖片與驗證頁面都要呼叫。?t=timestamp) 避免瀏覽器快取舊圖。php -m | grep gd 確認,Ubuntu apt install php-gd。