# Linux 編譯 ./configure --with-gd --with-freetype-dir --with-jpeg-dir --with-png-dir # Windows php.ini extension=php_gd2.dll ; 取消註解 ; 確認 phpinfo() 顯示 GD Support: enabled, FreeType Support: true
驗證:
<?php
if (extension_loaded('gd')) {
echo "GD 版本: " . gd_info()['GD Version'] . "\n";
print_r(gd_info());
} else {
die('請啟用 php_gd2.dll');
}
?>
<?php
/**
* 生成驗證碼圖片並存入 Session
* @param int $num 字元數
* @param int $size 字體大小
* @param int $width 圖片寬
* @param int $height 圖片高
*/
function vCode($num = 4, $size = 20, $width = 0, $height = 0) {
session_start();
// 尺寸自適應
!$width && $width = $num * $size * 4 / 5 + 10;
!$height && $height = $size + 15;
// 字元池 (排除易混淆: 0/O, 1/I/l)
$chars = '23456789abcdefghjkmnpqrstuvwxyzABCDEFGHJKMNPQRSTUVWXYZ';
$code = '';
for ($i = 0; $i < $num; $i++) {
$code .= $chars[mt_rand(0, strlen($chars) - 1)];
}
$_SESSION['verify_code'] = strtolower($code); // 統一小寫驗證
// 建立真彩色圖片
$im = imagecreatetruecolor($width, $height);
// 顏色分配
$bgColor = imagecolorallocate($im, 235, 236, 237); // 淺灰背景
$borderColor = imagecolorallocate($im, 118, 151, 199); // 藍邊框
$textColor = imagecolorallocate($im, mt_rand(0, 100), mt_rand(0, 100), mt_rand(0, 100)); // 深色文字
// 填充背景
imagefilledrectangle($im, 0, 0, $width, $height, $bgColor);
// 畫邊框
imagerectangle($im, 0, 0, $width - 1, $height - 1, $borderColor);
// 干擾線 (5 條)
for ($i = 0; $i < 5; $i++) {
$lineColor = imagecolorallocate($im, mt_rand(0, 255), mt_rand(0, 255), mt_rand(0, 255));
imageline($im,
mt_rand(0, $width), mt_rand(0, $height),
mt_rand(0, $width), mt_rand(0, $height),
$lineColor
);
}
// 干擾點 (50 個)
for ($i = 0; $i < 50; $i++) {
$dotColor = imagecolorallocate($im, mt_rand(0, 255), mt_rand(0, 255), mt_rand(0, 255));
imagesetpixel($im, mt_rand(0, $width), mt_rand(0, $height), $dotColor);
}
// 繪製文字 (需 TTF 字體支援中文/特殊字體)
// Windows 字體路徑範例: 'C:/Windows/Fonts/arial.ttf'
// Linux: '/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf'
$fontFile = 'C:/Windows/Fonts/arial.ttf'; // 請根據環境修改
if (file_exists($fontFile)) {
imagettftext($im, $size, mt_rand(-10, 10), 10, $size + 5, $textColor, $fontFile, $code);
} else {
// 回退內建字體 (不支援中文、無旋轉)
imagestring($im, 5, 10, 5, $code, $textColor);
}
// 輸出
header('Cache-Control: no-store, no-cache, must-revalidate, max-age=0');
header('Pragma: no-cache');
header('Content-Type: image/png');
imagepng($im);
imagedestroy($im);
}
// 使用:
vCode();
?>
<?php
session_start();
$width = 120;
$height = 40;
$charCount = 6;
$font = __DIR__ . '/fonts/DejaVuSans.ttf'; // 需下載 TTF 字體
$chars = '23456789bcdfghjkmnpqrstvwxyz'; // 無易混淆字元
$code = '';
for ($i = 0; $i < $charCount; $i++) {
$code .= $chars[mt_rand(0, strlen($chars) - 1)];
}
$_SESSION['captcha_code'] = strtolower($code);
$fontSize = $height * 0.75;
$im = imagecreatetruecolor($width, $height);
// 顏色 (十六進制轉 RGB)
function hex2rgb($hex) {
$hex = ltrim($hex, '#');
return [
'r' => hexdec(substr($hex, 0, 2)),
'g' => hexdec(substr($hex, 2, 2)),
'b' => hexdec(substr($hex, 4, 2))
];
}
$bg = imagecolorallocate($im, 255, 255, 255);
$textCol = imagecolorallocate($im, ...array_values(hex2rgb('142864')));
$noiseCol = imagecolorallocate($im, ...array_values(hex2rgb('142864')));
// 干擾點
for ($i = 0; $i < 10; $i++) {
imagefilledellipse($im, mt_rand(0, $width), mt_rand(0, $height), 2, 3, $noiseCol);
}
// 干擾線
for ($i = 0; $i < 20; $i++) {
imageline($im, mt_rand(0, $width), mt_rand(0, $height), mt_rand(0, $width), mt_rand(0, $height), $noiseCol);
}
// 計算文字居中位置
$box = imagettfbbox($fontSize, 0, $font, $code);
$x = ($width - ($box[2] - $box[0])) / 2;
$y = ($height - ($box[5] - $box[3])) / 2;
imagettftext($im, $fontSize, 0, $x, $y, $textCol, $font, $code);
header('Content-Type: image/jpeg');
imagejpeg($im, null, 90);
imagedestroy($im);
?>
<!-- HTML -->
<form action="login.php" method="post">
<input type="text" name="captcha" placeholder="輸入驗證碼" required>
<img id="captchaImg" src="captcha.php" alt="驗證碼" style="cursor:pointer;vertical-align:middle" title="點擊刷新">
<script>
document.getElementById('captchaImg').onclick = function() {
this.src = 'captcha.php?' + Date.now(); // 防緩存
};
</script>
<button type="submit">登入</button>
</form>
<?php
// login.php
session_start();
if (strtolower($_POST['captcha'] ?? '') !== ($_SESSION['captcha_code'] ?? '')) {
die('驗證碼錯誤');
}
// 正常登入邏輯...
?>
random_int 替代 mt_rand (PHP 7+):防止種子預測session_regenerate_id(true)fonts/ 目錄,確保 Web 進程可讀方案一適合快速原型、內部系統;方案二視覺更專業,適合面向用戶的正式產品。現代項目建議優先評估 reCAPTCHA v3 / hCaptcha 等無感驗證方案。