showImage() 直接輸出圖片、getCheckCode() 取得驗證碼字串<?php
class ValidationCode {
private $width;
private $height;
private $codeNum;
private $image;
private $disturbColorNum;
private $checkCode;
public function __construct($width = 80, $height = 20, $codeNum = 4) {
$this->width = $width;
$this->height = $height;
$this->codeNum = $codeNum;
$this->checkCode = $this->createCheckCode();
$number = floor($width * $height / 15);
$this->disturbColorNum = ($number > 240 - $codeNum) ? 240 - $codeNum : $number;
}
// 公開介面:輸出驗證碼圖片至瀏覽器
public function showImage($fontFace = "") {
$this->createImage();
$this->setDisturbColor();
$this->outputText($fontFace);
$this->outputImage();
}
// 公開介面:取得驗證碼字串 (供 Session 儲存比對)
public function getCheckCode() {
return $this->checkCode;
}
private function createImage() {
$this->image = imagecreatetruecolor($this->width, $this->height);
$backColor = imagecolorallocate($this->image, rand(225, 255), rand(225, 255), rand(225, 255));
imagefill($this->image, 0, 0, $backColor);
$border = imagecolorallocate($this->image, 0, 0, 0);
imagerectangle($this->image, 0, 0, $this->width - 1, $this->height - 1, $border);
}
private function setDisturbColor() {
// 噪點
for ($i = 0; $i < $this->disturbColorNum; $i++) {
$color = imagecolorallocate($this->image, rand(0, 255), rand(0, 255), rand(0, 255));
imagesetpixel($this->image, rand(1, $this->width - 2), rand(1, $this->height - 2), $color);
}
// 干擾弧線
for ($i = 0; $i < 10; $i++) {
$color = imagecolorallocate($this->image, rand(200, 255), rand(200, 255), rand(200, 255));
imagearc($this->image, rand(-10, $this->width), rand(-10, $this->height), rand(30, 300), rand(20, 200), 55, 44, $color);
}
}
private function createCheckCode() {
$code = "23456789abcdefghijkmnpqrstuvwxyzABCDEFGHIJKMNPQRSTUVWXYZ"; // 排除易混淆 0,O,1,l,I
$string = '';
for ($i = 0; $i < $this->codeNum; $i++) {
$string .= $code[rand(0, strlen($code) - 1)];
}
return $string;
}
private function outputText($fontFace = "") {
for ($i = 0; $i < $this->codeNum; $i++) {
$fontcolor = imagecolorallocate($this->image, rand(0, 128), rand(0, 128), rand(0, 128));
if ($fontFace == "") {
$fontsize = rand(3, 5);
$x = floor($this->width / $this->codeNum) * $i + 3;
$y = rand(0, $this->height - 15);
imagechar($this->image, $fontsize, $x, $y, $this->checkCode[$i], $fontcolor);
} else {
$fontsize = rand(12, 16);
$x = floor(($this->width - 8) / $this->codeNum) * $i + 8;
$y = rand($fontsize + 5, $this->height);
imagettftext($this->image, $fontsize, rand(-30, 30), $x, $y, $fontcolor, $fontFace, $this->checkCode[$i]);
}
}
}
private function outputImage() {
if (imagetypes() & IMG_GIF) {
header("Content-Type: image/gif");
imagegif($this->image);
} elseif (imagetypes() & IMG_JPG) {
header("Content-Type: image/jpeg");
imagejpeg($this->image);
} elseif (imagetypes() & IMG_PNG) {
header("Content-Type: image/png");
imagepng($this->image);
} elseif (imagetypes() & IMG_WBMP) {
header("Content-Type: image/vnd.wap.wbmp");
imagewbmp($this->image);
} else {
die("PHP 不支援圖像創建");
}
}
public function __destruct() {
if ($this->image) imagedestroy($this->image);
}
}
?>
code.php (驗證碼圖片輸出入口)
<?php
session_start();
require_once "validationcode.class.php";
$code = new ValidationCode(100, 30, 4); // 寬100 高30 4位字元
$code->showImage(); // 直接輸出圖片二進位
$_SESSION["verify_code"] = $code->getCheckCode(); // 儲存至 Session
?>
HTML 表單引用
<img src="code.php" id="captcha" onclick="this.src='code.php?'+Math.random()" style="cursor:pointer">
<input type="text" name="verify" placeholder="輸入驗證碼">
驗證邏輯
<?php
session_start();
if (strtoupper($_POST['verify']) === strtoupper($_SESSION['verify_code'])) {
echo "驗證通過";
} else {
echo "驗證碼錯誤";
}
?>
unset($_SESSION['verify_code']) 防止重複使用。imagepng 並啟用 HTTP 快取頭,或前端改用 JavaScript 生成 (如 Canvas)。