<?php
// reg.php
error_reporting(0); // 生產環境應配置日志而非關閉
session_start();
header("Cache-control: private");
// 數據庫連接(建議用 PDO/MySQLi 預處理)
$conn = @mysql_connect("localhost", "root", "") or die("數據庫連接失敗");
mysql_select_db("bbs", $conn);
mysql_query("SET NAMES utf8");
if ($_POST['submit']) {
$username = $_POST["username"];
// 1. 服務端檢查用戶名唯一性(核心邏輯)
$sql = "SELECT userName FROM user_info WHERE userName = '$username'";
$query = mysql_query($sql);
$rows = mysql_num_rows($query);
if ($rows > 0) {
echo "<script>alert('用戶名已存在'); history.back();</script>";
exit;
}
// 2. 插入新用戶(密碼 MD5,實際應用 bcrypt)
$sql = "INSERT INTO user_info (username, pass, sex, qq, email, img)
VALUES ('$username', MD5('{$_POST[pass]}'), '{$_POST[sex]}', '{$_POST[qq]}', '{$_POST[email]}', '{$_POST[img_select]}')";
mysql_query($sql);
echo "<script>alert('註冊成功'); location.href='login.php';</script>";
}
<form action="reg.php" name="reg_form" method="post" onsubmit="return checkReg()">
<table>
<tr><td>用戶:</td><td><input id="username" name="username" maxlength="12" /></td></tr>
<tr><td>性別:</td><td>
<input type="radio" name="sex" value="1">女
<input type="radio" name="sex" value="2">男
<input type="radio" name="sex" value="0" checked>保密
</td></tr>
<tr><td>密碼:</td><td><input name="pass" type="password" onblur="checkLen(this)"><span id="show_pass"></span></td></tr>
<tr><td>確認密碼:</td><td><input name="repass" type="password" onblur="checkPass(this)"><span id="show_repass"></span></td></tr>
<tr><td>QQ:</td><td><input name="qq" onblur="checkQq(this)"><span id="show_qq"></span></td></tr>
<tr><td>郵箱:</td><td><input name="email" onblur="checkEmail(this)"><span id="show_e"></span></td></tr>
<tr><td>頭像:</td><td>
<select name="img_select" onchange="imgChange(this)">
<option value="101">女001</option> ... <option value="108">男004</option>
</select>
<img id="tx_change" src="/bbs/img/101.gif">
</td></tr>
<tr><td><input type="submit" name="submit" value="註冊"></td><td><input type="reset" value="重置"></td></tr>
</table>
</form>
<script>
// 頭像預覽切換
function imgChange(obj) {
document.getElementById("tx_change").src = "/bbs/img/" + obj.value + ".gif";
}
// 總驗證入口
function checkReg() {
return checkLen() && checkPass() && checkEmail() && checkQq();
}
// 密碼長度 ≥ 6
function checkLen(obj) {
var el = document.getElementById('show_pass');
if (!obj.value.length) { el.innerHTML = "密碼不能為空"; return false; }
if (obj.value.length < 6) { el.innerHTML = "密碼長度不少於6位"; return false; }
el.innerHTML = ""; return true;
}
// 兩次密碼一致
function checkPass(obj) {
var pass = document.getElementById('pass').value;
var el = document.getElementById('show_repass');
if (!pass.length) { document.getElementById('show_pass').innerHTML = "密碼不能為空"; return false; }
if (obj.value !== pass) { el.innerHTML = "兩次密碼不一致"; return false; }
el.innerHTML = ""; return true;
}
// 郵箱格式
function checkEmail(obj) {
var reg = /^([a-zA-Z\d][a-zA-Z0-9_]+@[a-zA-Z\d]+(\.[a-zA-Z\d]+)+)$/gi;
var el = document.getElementById('show_e');
if (!obj.value.length) { el.innerHTML = "Email不能為空"; return false; }
if (!reg.test(obj.value)) { el.innerHTML = "Email格式不正確"; return false; }
el.innerHTML = ""; return true;
}
// QQ 純數字
function checkQq(obj) {
var reg = /^\d+$/;
var el = document.getElementById('show_qq');
if (!reg.test(obj.value)) { el.innerHTML = "QQ只能為數字"; return false; }
el.innerHTML = ""; return true;
}
</script>
| 問題 | 風險 | 升級方案 |
|---|---|---|
| mysql_* 函數 | PHP 7.0+ 已移除、無預處理、SQL注入風險 | 改用 PDO 或 MySQLi 預處理語句 |
| 密碼 MD5 | 極不安全、彩虹表秒破 | 用 password_hash() (bcrypt/Argon2) |
| 前端校驗可繞過 | 直接 POST 繞過 JS | 後端必須完整校驗(已做),前端僅提升 UX |
| 錯誤輸出內聯 JS | XSS 風險、難維護 | 返回 JSON,前端統一處理提示/跳轉 |
| 無 CSRF Token | 跨站請求偽造 | 表單隱藏字段 + 服務端驗證 Token |
| 明文傳輸 | 密碼竊聽 | 全站 HTTPS |
<?php
// API 端點 /api/register
$input = json_decode(file_get_contents('php://input'), true);
$validator = new Validator($input, [
'username' => 'required|alpha_dash|unique:users',
'password' => 'required|min:8|confirmed',
'email' => 'required|email|unique:users',
]);
if ($validator->fails()) {
return response()->json(['errors' => $validator->errors()], 422);
}
$user = User::create([
'username' => $input['username'],
'password' => bcrypt($input['password']),
'email' => $input['email'],
]);
return response()->json(['user' => $user], 201);
經典示例展示了核心邏輯,生產環境務必套用現代框架(Laravel/ThinkPHP6/Symfony)的驗證、ORM、安全組件。