檔案:checkcode.php
<?php
session_start();
function random($len) {
$srcstr = "1a2s3d4f5g6hj8k9qwertyupzxcvbnm"; // 排除易混淆字元
$str = '';
for ($i = 0; $i < $len; $i++) {
$str .= $srcstr[mt_rand(0, strlen($srcstr) - 1)];
}
return $str;
}
// 產生 4 碼隨機字串
$code = random(4);
// 圖片尺寸
$width = 100;
$height = 35;
// 建立畫布
$im = imagecreatetruecolor($width, $height);
// 顏色分配
$bg = imagecolorallocate($im, 255, 255, 255); // 白底
$noise = imagecolorallocate($im, 180, 230, 245); // 干擾點
$text = imagecolorallocate($im, 41, 163, 238); // 文字藍
$border = imagecolorallocate($im, 41, 163, 238); // 邊框
// 填滿背景
imagefill($im, 0, 0, $bg);
// 繪製干擾點
for ($i = 0; $i < 800; $i++) {
imagesetpixel($im, mt_rand(0, $width), mt_rand(0, $height), $noise);
}
// 繪製干擾線(增強反機器人)
for ($i = 0; $i < 5; $i++) {
$line_color = imagecolorallocate($im, mt_rand(150,200), mt_rand(150,200), mt_rand(150,200));
imageline($im, mt_rand(0,$width), mt_rand(0,$height), mt_rand(0,$width), mt_rand(0,$height), $line_color);
}
// 繪製文字(使用 TTF 字型更佳)
// imagettftext($im, 20, 0, 15, 28, $text, __DIR__.'/fonts/arial.ttf', $code);
// 簡易版:
imagestring($im, 5, 20, 8, $code, $text);
// 邊框
imagerectangle($im, 0, 0, $width-1, $height-1, $border);
// 輸出
header('Content-Type: image/png');
imagepng($im);
imagedestroy($im);
// 存入 Session(MD5 加密儲存,驗證時比對 MD5)
$_SESSION['verify_code'] = md5(strtolower($code)); // 不分大小寫
<!-- HTML -->
<img id="captcha" src="checkcode.php" alt="驗證碼" style="cursor:pointer;vertical-align:middle;" />
<a href="javascript:void(0);" onclick="refreshCaptcha()">看不清?換一張</a>
<input type="text" name="captcha" placeholder="輸入驗證碼" />
<script>
function refreshCaptcha() {
// 加隨機參數防止瀏覽器快取
document.getElementById('captcha').src = 'checkcode.php?' + Math.random();
}
</script>
<?php
session_start();
$userInput = strtolower($_POST['captcha'] ?? '');
$stored = $_SESSION['verify_code'] ?? '';
if (md5($userInput) === $stored) {
echo "驗證通過";
// 清除已用驗證碼,防止重放
unset($_SESSION['verify_code']);
} else {
echo "驗證碼錯誤";
}
| 措施 | 說明 |
|---|---|
| 使用 TTF 字型 + 旋轉/扭曲 | imagettftext() 配合隨機角度、字距,大幅提高 OCR 識別難度 |
| Session 儲存加鹽雜湊 | hash('sha256', $code . $secret),避免 Session 被竊取直接破解 |
| 限制驗證碼使用次數/時間 | 驗證成功即刪除、超時 5-10 分鐘失效 |
| 無障礙替代方案 | 提供語音驗證碼或簡單數學題(如 3+5=?) |
| 現代替代方案 | Google reCAPTCHA v3、hCaptcha、Turnstile(行為分析、無感驗證) |
checkcode.php 前無輸出(空白行、BOM)、GD 擴展已安裝、header() 在輸出前呼叫session_start() 在所有輸出前、Cookie 設定正確、跨域需 session_set_cookie_params()strtolower() 或 mb_strtolower()