本文提供一個完整的「前端 AJAX + 後端 PHP + MySQL」使用者註冊系統範例,包含使用者名即時檢查、驗證碼生成與驗證、照片上傳、表單驗證、資料庫操作、SQL 注入防護等核心功能,適合學習 AJAX 互動流程與 PHP 後端處理的開發者參考。
test 資料庫與 user 表onblur 觸發 checkusername()、checkcode() 即時驗證XMLHttpRequest 相容 IE 與現代瀏覽器checkform() 做必填驗證<td id="pmt_*"><?php
$username = $_GET['username'];
mysql_connect('127.0.0.1', 'root', '') or die('connect failed');
mysql_select_db('test');
// 防 SQL 注入:轉義特殊字元並加引號
$username = htmlentities($username, ENT_QUOTES);
$sql = "SELECT COUNT(*) FROM user WHERE username = '{$username}'";
$result = mysql_query($sql);
if ($row = mysql_fetch_array($result, MYSQL_NUM)) {
$cnt = $row[0];
echo $cnt == 0 ? '使用者名未被使用' : '使用者名已被使用,請改換使用者名';
}
?>
注意:範例使用已棄用的 mysql_* 函式,實務請改用 PDO 或 MySQLi 預處理語句。
<?php
session_start();
$rnd = array_merge(range(0,9), range('a','z'));
shuffle($rnd);
$code = substr(implode('', $rnd), 0, 4);
$_SESSION['verifycode'] = $code;
header("Content-Type: image/png");
$im = @imagecreate(50, 25) or die("GD error");
$bg = imagecolorallocate($im, 255, 255, 255);
$text = imagecolorallocate($im, 233, 14, 91);
imagestring($im, 5, 5, 5, $code, $text);
imagepng($im);
imagedestroy($im);
?>
<?php
session_start();
$code = $_GET['code'];
echo strtoupper($code) == $_SESSION['verifycode'] ? '驗證碼正確' : '驗證碼錯誤';
?>
<?php
session_start();
// 1. 照片上傳處理
$filename = '';
if (isset($_FILES['photo'])) {
$uploaddir = dirname(__FILE__) . DIRECTORY_SEPARATOR . 'upload';
$origin = $_FILES['photo']['name'];
$ext = strtolower(substr($origin, strrpos($origin, '.') + 1));
$filename = time() . '.' . $ext;
$validExt = ['jpg','jpeg','gif','png'];
if (!in_array($ext, $validExt)) { die('錯誤的檔案類型'); }
if ($_FILES['photo']['size'] > 100*1024) { die('檔案太大,超過 100KB'); }
$uploadfile = $uploaddir . DIRECTORY_SEPARATOR . $filename;
if (!move_uploaded_file($_FILES['photo']['tmp_name'], $uploadfile)) {
die('照片上傳失敗');
}
}
// 2. 驗證碼複核
if ($_POST['verifycode'] != $_SESSION['verifycode']) {
die('驗證碼輸入不正確');
}
// 3. 資料庫寫入
mysql_connect('127.0.0.1', 'root', '');
mysql_select_db('test');
mysql_query('SET NAMES utf8');
$username = addslashes($_POST['username']);
$pwd = md5($_POST['pwd']);
$name = addslashes($_POST['name']);
$sex = addslashes($_POST['sex']);
$age = intval($_POST['age']);
$mobile = addslashes($_POST['mobile']);
$address = addslashes($_POST['address']);
$email = addslashes($_POST['email']);
$photo = $filename;
$birthday = addslashes($_POST['birthday']);
$sql = "INSERT INTO user (username,pwd,name,sex,age,mobile,address,email,photo,birthday)
VALUES ('$username','$pwd','$name','$sex',$age,'$mobile','$address','$email','$photo','$birthday')";
if (!mysql_query($sql)) {
die('資料庫寫入失敗');
}
// 4. 顯示所有使用者
$sql = 'SELECT * FROM user';
$res = mysql_query($sql);
echo "<table><tr><td>使用者名</td><td>姓名</td>...</tr>";
while ($row = mysql_fetch_assoc($res)) {
echo "<tr><td>{$row['username']}</td>...";
}
echo "</table>";
?>
DROP DATABASE IF EXISTS test;
CREATE DATABASE test CHARACTER SET utf8 COLLATE utf8_general_ci;
USE test;
CREATE TABLE user (
username CHAR(10) PRIMARY KEY,
pwd CHAR(32) NOT NULL,
name CHAR(10) NOT NULL,
sex CHAR(1) NOT NULL,
mobile CHAR(11),
age SMALLINT,
address VARCHAR(50),
email VARCHAR(30),
photo VARCHAR(20),
birthday DATE
);
| 問題 | 風險 | 改進方案 |
|---|---|---|
| 使用 mysql_* 函式 | PHP 7.0+ 移除,無預處理機制 | 改用 PDO 或 MySQLi Prepared Statements |
| addslashes 防注入 | 不完整,編碼問題導致繞過 | 參數綁定(Prepared Statements) |
| 密碼用 MD5 | 極易碰撞、彩虹表破解 | 使用 password_hash() / password_verify() (bcrypt/argon2) |
| 驗證碼僅 4 碼英數 | 易被暴力破解、OCR 識別 | 加長長度、加入干擾線、使用 Google reCAPTCHA/hCaptcha |
| 檔案上傳僅驗證副檔名 | 可上傳惡意腳本偽裝圖片 | 驗證 MIME (finfo_file)、移除執行權限、儲存非公開目錄 |
| 錯誤直接 die() 輸出 | 資訊洩露、體驗差 | 統一異常處理、回傳 JSON 錯誤碼、前端友善提示 |
| 無 CSRF Token | 跨站請求偽造 | 表單隱藏欄位加入 CSRF Token,後端驗證 |