完整實現
<?php
session_start();
$width = 120;
$height = 40;
$len = 4; // 驗證碼長度
$charset = '0123456789abcdef'; // 十六進制,可擴充字母
// 1. 生成隨機碼存 Session
$code = '';
for ($i=0; $i<$len; $i++) {
$code .= $charset[mt_rand(0, strlen($charset)-1)];
}
$_SESSION['captcha'] = $code;
// 2. 建立畫布
$im = imagecreatetruecolor($width, $height);
$white = imagecolorallocate($im, 255, 255, 255);
$black = imagecolorallocate($im, 0, 0, 0);
imagefilledrectangle($im, 0, 0, $width-1, $height-1, $white);
imagerectangle($im, 0, 0, $width-1, $height-1, $black);
// 3. 繪製雪花干擾(100 個半透明 *)
for ($i=0; $i<100; $i++) {
$color = imagecolorallocatealpha($im,
mt_rand(200,255), mt_rand(200,255), mt_rand(200,255), 60);
imagestring($im, 1,
mt_rand(1,$width), mt_rand(1,$height),
'*', $color);
}
// 4. 繪製驗證碼字符(逐字隨機屬性)
for ($i=0; $i<$len; $i++) {
$color = imagecolorallocate($im,
mt_rand(0,100), mt_rand(0,150), mt_rand(0,200));
$size = mt_rand(3,5); // 字體大小 3-5
$x = $i * $width/$len + mt_rand(5,15);
$y = mt_rand(5,$height/2);
imagestring($im, $size, $x, $y, $code[$i], $color);
}
// 5. 輸出
header('Content-Type: image/png');
imagepng($im);
imagedestroy($im);
驗證端
<?php
session_start();
if (strtolower($_POST['captcha'] ?? '') !== strtolower($_SESSION['captcha'] ?? '')) {
exit('驗證碼錯誤');
}
// 通過,執行業務邏輯
安全強化清單
- 字符集擴大:大小寫字母 + 數字,排除易混淆字符 (0/O, 1/I/l)。
- 增加干擾線:
imageline() 隨機畫 3-5 條曲線。
- 字符旋轉/扭曲:
imagerotate() 或逐像素位移。
- Session 驗證碼用後即銷毀:
unset($_SESSION['captcha'])。
- 限制請求頻率:同 IP 分鐘內最多請求 5 次驗證碼圖片。
- 考慮現代替代:Google reCAPTCHA v3 / hCaptcha / Turnstile(行為分析、無感驗證)。