驗證碼是表單防機器人基本防線。本文提供功能完整的 Captcha 類別,支援自訂長度、寬高、干擾線條數、雜點數量、字體大小範圍、顏色隨機化,並內建 Session 存取與驗證邏輯,可直接整合至登入、註冊、留言等表單。
<?php
class Captcha {
private $sname = '';
public function __construct($sname='') {
$this->sname = $sname==='' ? 'm_captcha' : $sname;
}
// 生成並輸出圖片
public function create($length=4, $param=array()) {
header("Content-Type: image/png");
$code = $this->random($length);
$this->captcha_session($this->sname, $code);
$w = isset($param['width']) ? $param['width'] : 13;
$h = isset($param['height']) ? $param['height'] : 18;
$pnum = isset($param['pnum']) ? $param['pnum'] : 100;
$lnum = isset($param['lnum']) ? $param['lnum'] : 2;
$img_w = $w * $length + 10;
$img_h = $h + 6;
$im = imagecreate($img_w, $img_h);
$bg = imagecolorallocate($im, 238, 238, 238);
// 隨機多邊形背景干擾
$pts = array();
for ($i=0;$i<6;$i++) $pts[] = mt_rand(0,$img_w), $pts[] = mt_rand(0,$img_h);
imagefilledpolygon($im, $pts, 6, imagecolorallocate($im, mt_rand(170,255), mt_rand(200,255), mt_rand(210,255)));
// 繪製字元
for ($i=0; $i<$length; $i++) {
$color = imagecolorallocate($im, mt_rand(0,50), mt_rand(0,150), mt_rand(0,200));
$x = $i/$length * $img_w + mt_rand(1,6);
$y = mt_rand(1, $img_h/3);
imagestring($im, mt_rand(4,6), $x, $y, $code[$i], $color);
}
// 雜點
for ($i=0; $i<$pnum; $i++) {
imagesetpixel($im, mt_rand(0,$img_w), mt_rand(0,$img_h), imagecolorallocate($im, mt_rand(0,255), mt_rand(0,255), mt_rand(0,255)));
}
// 干擾線
for ($i=0; $i<$lnum; $i++) {
imageline($im, mt_rand(0,$img_w), mt_rand(0,$img_h), mt_rand(0,$img_w), mt_rand(0,$img_h), imagecolorallocate($im, mt_rand(50,255), mt_rand(150,255), mt_rand(200,255)));
}
imagepng($im);
imagedestroy($im);
exit;
}
// 驗證使用者輸入
public function check($captcha, $flag=1) {
if (empty($captcha)) return false;
if (strtoupper($captcha) === $this->captcha_session($this->sname)) {
if ($flag==1) $this->captcha_session($this->sname, '');
return true;
}
return false;
}
private function random($len) {
$chars = 'ABCDEFGHIJKLMNPQRSTUVWXYZ23456789'; // 排除易混淆 0/O/I/1
$code = '';
for ($i=0;$i<$len;$i++) $code .= $chars[mt_rand(0, strlen($chars)-1)];
return $code;
}
private function captcha_session($name,$value=null) {
if (session_id()==='') session_start();
if ($value!==null) { if ($value!=='') $_SESSION[$name]=$value; else unset($_SESSION[$name]); }
else return isset($_SESSION[$name]) ? $_SESSION[$name] : '';
}
}
?>
<?php
session_start();
require_once 'Captcha.class.php';
$captcha = new Captcha('login_captcha');
if (isset($_GET['captcha_img'])) {
$captcha->create(4, array('width'=>15,'height'=>22,'pnum'=>80,'lnum'=>3));
exit;
}
if ($_SERVER['REQUEST_METHOD']==='POST') {
$user = trim($_POST['username']);
$code = trim($_POST['captcha_code']);
if ($captcha->check($code)) {
echo "登入成功:$user";
} else {
echo "驗證碼錯誤";
}
exit;
}
?>
<!DOCTYPE html>
<html><head><meta charset="utf-8"><title>登入</title></head><body>
<form method="post">
<p>帳號:<input name="username" required></p>
<p>驗證碼:<input name="captcha_code" required>
<img src="?captcha_img=1&t=<?=time()?>" onclick="this.src='?captcha_img=1&t='+Date.now()" style="cursor:pointer;vertical-align:middle" title="點擊換圖"></p>
<button>登入</button>
</form>
</body></html>
| 參數 | 預設 | 建議範圍 | 影響 |
|---|---|---|---|
| length | 4 | 4-6 | 越長越難破解,但使用者負擔增大 |
| width | 13 | 12-20 | 字元寬度,影響圖片總寬度 |
| height | 18 | 18-30 | 字元高度,影響辨識難度 |
| pnum | 100 | 50-200 | 雜點密度,過高影響人類辨識 |
| lnum | 2 | 1-5 | 干擾線條數 |
imagettftext + TTF 字體,支援旋轉、扭曲、字距隨機化。完整原始碼可至本站下載。此類別適合中小型專案快速整合,高安全性需求建議採用 reCAPTCHA v3、hCaptcha 等行為分析型方案。