圖形驗證碼(CAPTCHA)透過生成機器難以辨識、人類易於閱讀的圖片,有效防止自動化腳本惡意註冊、暴力破解等攻擊。本文實作一個經典的 4 位數字驗證碼,包含干擾線、噪點與字元隨機偏移。
<?php
session_start();
// 1. 生成 4 位隨機數字
$code = '';
for ($i = 0; $i < 4; $i++) {
$code .= mt_rand(0, 9);
}
// 替代寫法:$code = str_pad(mt_rand(0, 9999), 4, '0', STR_PAD_LEFT);
// 2. 存入 Session 供驗證使用
$_SESSION['captcha_code'] = $code;
// 3. 建立圖片畫布 (寬 100px, 高 35px)
$width = 100;
$height = 35;
$im = imagecreatetruecolor($width, $height);
// 4. 分配顏色
$bg_color = imagecolorallocate($im, 230, 230, 230); // 淺灰背景
$text_color = imagecolorallocate($im, 0, 0, 0); // 黑色文字
$line_color = imagecolorallocate($im, 150, 150, 150); // 灰色干擾線
$dot_color = imagecolorallocate($im, 100, 100, 100); // 深灰噪點
// 5. 填充背景
imagefill($im, 0, 0, $bg_color);
// 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),
$line_color
);
}
// 7. 繪製噪點 (80 個)
for ($i = 0; $i < 80; $i++) {
imagesetpixel($im, mt_rand(0, $width), mt_rand(0, $height), $dot_color);
}
// 8. 繪製驗證碼文字 (隨機位置與角度)
$font_size = 5; // 內建字體 1-5
$x = 10;
for ($i = 0; $i < 4; $i++) {
$y = mt_rand(8, 22);
$angle = mt_rand(-15, 15);
// 使用 imagettftext 可載入 TTF 字體獲得更好效果
imagestring($im, $font_size, $x, $y, $code[$i], $text_color);
$x += mt_rand(18, 24); // 隨機字元間距
}
// 9. 輸出圖片並釋放資源
header('Content-Type: image/png');
imagepng($im);
imagedestroy($im);
<form method="post" action="check_register.php">
<div>
<label>帳號:</label>
<input type="text" name="username" required>
</div>
<div>
<label>驗證碼:</label>
<input type="text" name="captcha" maxlength="4" size="6" required>
<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>
<?php
session_start();
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$input_code = trim($_POST['captcha']);
$session_code = $_SESSION['captcha_code'] ?? '';
// 驗證碼比對 (不分大小寫,此處純數字無影響)
if (strtolower($input_code) !== strtolower($session_code)) {
die('驗證碼錯誤,請返回重試');
}
// 驗證通過,執行註冊邏輯...
echo '註冊成功!';
// 用完即銷毀,防止重複使用
unset($_SESSION['captcha_code']);
}
| 增強項目 | 實作方式 | 效果 |
|---|---|---|
| 字元類型擴充 | 加入大小寫英文、特殊符號 | 大幅提高破解難度 |
| TTF 字體渲染 | 使用 imagettftext + 自訂字體檔 | 字體扭曲、旋轉更自然 |
| 幾何扭曲 | imageaffine / imagefilter 濾鏡 | 干擾 OCR 辨識演算法 |
| 語音驗證碼 | TTS 生成音檔給視障用戶 | 符合無障礙網頁規範 |
| 行為驗證 | 整合 Google reCAPTCHA v3 | 零互動、風險評分機制 |
session.cookie_httponly、session.use_strict_modeunset,防止重放攻擊php -m | grep gd),確認輸出前無任何空白字元或 BOM。session_start(),且在任何輸出前呼叫。