ImageCode 類別完整程式碼
<?php
class ImageCode {
private $width, $height, $count, $disturbCode, $fontFile, $sessionCode;
public function __construct($width=120, $height=40, $count=4, $disturbCode='ABCDEFGHJKLMNPQRSTUVWXYZ23456789', $fontFile='') {
$this->width = $width;
$this->height = $height;
$this->count = $count;
$this->disturbCode = $disturbCode;
$this->fontFile = $fontFile ?: 'C:/Windows/Fonts/arial.ttf'; // 預設字型路徑
$this->sessionCode = $this->generateCode();
session_start();
$_SESSION['verify_code'] = $this->sessionCode;
}
public function output() {
$im = $this->createCanvas();
$this->drawBackground($im);
$this->drawDisturb($im);
$this->drawCode($im);
header("Content-Type: image/gif");
imagegif($im);
imagedestroy($im);
}
private function createCanvas() {
return imagecreate($this->width, $this->height);
}
private function drawBackground($im) {
$bg = imagecolorallocate($im, mt_rand(200,255), mt_rand(200,255), mt_rand(200,255));
imagefill($im, 0, 0, $bg);
}
private function drawDisturb($im) {
$lines = $this->height * 2;
for ($i=0; $i<$lines; $i++) {
$x = mt_rand(0, $this->width);
$y = mt_rand(0, $this->height);
$angle = mt_rand(0, 360);
$size = mt_rand(8, 15);
$char = $this->disturbCode[mt_rand(0, strlen($this->disturbCode)-1)];
$color = imagecolorallocate($im, mt_rand(40,140), mt_rand(40,140), mt_rand(40,140));
imagettftext($im, $size, $angle, $x, $y, $color, $this->fontFile, $char);
}
}
private function drawCode($im) {
$y = $this->height/2 + $this->height/4;
$size = mt_rand(20, 30);
for ($i=0; $i<$this->count; $i++) {
$char = $this->sessionCode[$i];
$x = ($this->width / $this->count) * $i + 8;
$angle = mt_rand(-20, 20);
$color = imagecolorallocate($im, mt_rand(0,50), mt_rand(50,100), mt_rand(100,140));
imagettftext($im, $size, $angle, $x, $y, $color, $this->fontFile, $char);
}
}
private function generateCode() {
$code = '';
$len = strlen($this->disturbCode);
for ($i=0; $i<$this->count; $i++) {
$code .= $this->disturbCode[mt_rand(0, $len-1)];
}
return $code;
}
public static function verify($input) {
session_start();
return isset($_SESSION['verify_code']) && strtoupper($input) === strtoupper($_SESSION['verify_code']);
}
}
?>
使用方式
1. 產生驗證碼圖片 (captcha.php)
<?php
require_once 'ImageCode.php';
header("Content-Type: image/gif");
$captcha = new ImageCode(130, 40, 4);
$captcha->output();
2. 表單驗證
<form action="check.php" method="post">
驗證碼: <input name="code" />
<img src="captcha.php" onclick="this.src='captcha.php?'+Math.random()" style="cursor:pointer" title="點擊更換"/>
<input type="submit" />
</form>
3. 後端驗證 (check.php)
<?php
require_once 'ImageCode.php';
if (ImageCode::verify($_POST['code'])) {
echo "驗證通過";
} else {
echo "驗證碼錯誤";
}
部署注意事項
- 字型檔案:Linux 伺服器需上傳 TTF 字型檔,並指定正確路徑
- GD/FreeType:PHP 編譯需支援
--with-freetype-dir 才能使用 imagettftext()
- Session 生命週期:驗證碼 Session 應設較短過期時間 (如 5-10 分鐘)
- 安全性:生成的驗證碼儲存在 Session 而非 Cookie,防止客戶端竄改
現代化替代方案
- Google reCAPTCHA v3:無感驗證,依行為評分
- hCaptcha:隱私優先,支援中文
- Slider/Click 驗證:前端互動式,體驗更佳
- 後端速率限制:配合 Redis 限制 IP/帳號請求頻率,減少驗證碼彈出機率