You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PHP注册表单跳过校验直接写入数据库问题修复方案

问题根因

代码存在5类核心问题,导致校验逻辑完全失效,空数据直接入库:

  • 校验逻辑与入库逻辑之间无拦截判断:无论$errorMsg是否存在错误,代码都会无条件执行后续PDO插入操作
  • 后端变量名拼写错误:校验姓氏时判断的是empty($lastname),但接收表单值存储的变量为$surname,该校验规则永远不会触发
  • 下拉选项默认值未做拦截:性别、种族下拉框默认值为字符串0,PHP中empty("0")会被判定为空,但原有逻辑未拦截该默认值,会把未选择的0值当成合法数据写入
  • 前端错误输出逻辑错误:一是PHP字符串拼接语法错误,变量被包裹在单引号内无法解析;二是除姓名字段外,其余字段的错误循环都错误引用了$nameErrors变量,导致对应错误无法正常显示
  • 缺失必要校验与安全处理:无邮箱格式校验、无用户条款同意校验、密码明文存储、未处理用户名/邮箱重复注册的场景、未做表单值回填,用户提交失败后需要重新填写所有内容
修复方案

采用标准的POST-Redirect-GET模式处理表单,校验不通过时携带错误信息和旧输入跳回注册页,校验完全通过后才执行入库操作。

1. 后端处理文件(includes/register-inc.php)修复

<?php
// 开启session用于跨页面传递错误信息和旧表单值
session_start();

if(isset($_POST["submit"])) {
    // 初始化错误数组,避免未定义变量报错
    $errorMsg = [];

    // 接收表单数据,先做默认值处理避免未定义索引报错
    $name = isset($_POST["name"]) ? trim($_POST["name"]) : '';
    $surname = isset($_POST["surname"]) ? trim($_POST["surname"]) : '';
    $gender = isset($_POST["gender"]) ? trim($_POST["gender"]) : '';
    $race = isset($_POST["race"]) ? trim($_POST["race"]) : '';
    $email = isset($_POST["email"]) ? strtolower(trim($_POST["email"])) : '';
    $username = isset($_POST["username"]) ? trim($_POST["username"]) : '';
    $pwd = isset($_POST["password"]) ? $_POST["password"] : '';
    $pwdRepeat = isset($_POST["retype_password"]) ? $_POST["retype_password"] : '';
    $terms = isset($_POST["terms"]) ? $_POST["terms"] : '';
    $joined = date("Y-m-d H:i:s");

    // 字段规则校验
    if(empty($name)) {
        $errorMsg[0][] = "Name required!"; 
    }
    // 修正之前写错的变量名$lastname为$surname
    if(empty($surname)) {
        $errorMsg[1][] = "Last name required!"; 
    }
    // 拦截下拉框默认0值
    if(empty($gender) || $gender == '0') {
        $errorMsg[2][] = "Please select gender!"; 
    }
    // 拦截下拉框默认0值
    if(empty($race) || $race == '0') {
        $errorMsg[3][] = "Please select your race!"; 
    }
    if(empty($email)) {
        $errorMsg[4][] = "Email required!"; 
    } elseif(!filter_var($email, FILTER_VALIDATE_EMAIL)) {
        $errorMsg[4][] = "Invalid email format!";
    }
    if(empty($username)) {
        $errorMsg[5][] = "Username required!"; 
    }
    if(empty($pwd)) {
        $errorMsg[6][] = "Password required!"; 
    } elseif(strlen($pwd) < 8) {
        $errorMsg[6][] = "Password must be at least 8 characters"; 
    }
    if($pwd !== $pwdRepeat) {
        $errorMsg[7][] = "Password don't match!"; 
    }
    // 增加条款同意校验
    if($terms !== 'accepted') {
        $errorMsg[8][] = "You must accept the terms and conditions to register!";
    }

    // 核心拦截逻辑:无任何错误时才执行数据库入库
    if(empty($errorMsg)) {
        try {
            $pdo = require_once '../classes/DB.php';
            // 密码哈希加密,禁止明文存储
            $hashedPwd = password_hash($pwd, PASSWORD_DEFAULT);

            $query = 'INSERT INTO users (name, surname, gender, race, email, username, password, joined) VALUES (?, ?, ?, ?, ?, ?, ?, ?)';
            $stmt = $pdo->prepare($query);
            $stmt->execute([$name, $surname, $gender, $race, $email, $username, $hashedPwd, $joined]);

            $register_id = $pdo->lastInsertId();
            // 注册成功存提示信息,跳转到登录页
            $_SESSION["success_msg"] = 'You have successfully registered as register id ' . $register_id . '. You may proceed to login.';
            header("Location: ../login.php");
            exit();
        } catch (PDOException $e) {
            // 处理唯一约束冲突(用户名/邮箱重复)
            if(str_contains($e->getMessage(), 'username')) {
                $errorMsg[5][] = "This username is already taken!";
            } elseif(str_contains($e->getMessage(), 'email')) {
                $errorMsg[4][] = "This email is already registered!";
            } else {
                $errorMsg[] = ["Registration failed, please try again later."];
            }
        }
    }

    // 存在错误时,把错误和旧表单值存入session,跳回注册页
    $_SESSION["errorMsg"] = $errorMsg;
    $_SESSION["old_input"] = $_POST;
    header("Location: ../register.php");
    exit();
}
// 非POST请求直接跳回注册页
header("Location: ../register.php");
exit();
?>

2. 前端注册页(register.php)修复

<?php
// 开启session
session_start();
// 取出错误信息和旧表单值,读取后立即清除避免刷新重复显示
$errorMsg = isset($_SESSION["errorMsg"]) ? $_SESSION["errorMsg"] : [];
$oldInput = isset($_SESSION["old_input"]) ? $_SESSION["old_input"] : [];
unset($_SESSION["errorMsg"], $_SESSION["old_input"]);
?>
<form action="includes/register-inc.php" method="post">
    <?php 
        if(isset($errorMsg[0])) {
            foreach($errorMsg[0] as $nameErrors) {
                // 修正字符串拼接错误
                echo '<p class="error-msg">'.$nameErrors.'</p>';
            }
        }
    ?>
    <!-- 回填用户之前输入的内容 -->
    <input type="text" name="name" placeholder="Type your firstname(s)" value="<?php echo isset($oldInput['name']) ? htmlspecialchars($oldInput['name']) : ''; ?>">
    
    <?php 
        if(isset($errorMsg[1])) {
            foreach($errorMsg[1] as $surnameErrors) {
                // 修正错误引用的变量名
                echo '<p class="error-msg">'.$surnameErrors.'</p>';
            }
        }
    ?>
    <input type="text" name="surname" placeholder="Type your surname" value="<?php echo isset($oldInput['surname']) ? htmlspecialchars($oldInput['surname']) : ''; ?>">
    
    <div class="row">
        <?php 
            if(isset($errorMsg[2])) {
                foreach($errorMsg[2] as $genderErrors) {
                    echo '<p class="error-msg">'.$genderErrors.'</p>';
                }
            }
        ?>
        <select name="gender" class="gender">
            <option value="0" selected disabled>Select your Gender</option> 
            <option value="male" <?php echo (isset($oldInput['gender']) && $oldInput['gender'] == 'male') ? 'selected' : ''; ?>>Male</option> 
            <option value="female" <?php echo (isset($oldInput['gender']) && $oldInput['gender'] == 'female') ? 'selected' : ''; ?>>Female</option> 
        </select>
        
        <?php 
        if(isset($errorMsg[3])) {
            foreach($errorMsg[3] as $raceErrors) {
                echo '<p class="error-msg">'.$raceErrors.'</p>';
            }
        }
        ?>
        <select name="race" class="race">
            <option value="0" selected disabled>Select your Race</option> 
            <option value="african" <?php echo (isset($oldInput['race']) && $oldInput['race'] == 'african') ? 'selected' : ''; ?>>African</option>
            <option value="asian" <?php echo (isset($oldInput['race']) && $oldInput['race'] == 'asian') ? 'selected' : ''; ?>>Asian</option> 
            <option value="caucasian" <?php echo (isset($oldInput['race']) && $oldInput['race'] == 'caucasian') ? 'selected' : ''; ?>>Caucasian</option>
            <option value="mixed-race" <?php echo (isset($oldInput['race']) && $oldInput['race'] == 'mixed-race') ? 'selected' : ''; ?>>Mixed Race</option> 
            <option value="indian" <?php echo (isset($oldInput['race']) && $oldInput['race'] == 'indian') ? 'selected' : ''; ?>>Indian</option> 
            <option value="other" <?php echo (isset($oldInput['race']) && $oldInput['race'] == 'other') ? 'selected' : ''; ?>>Other</option> 
        </select>
    </div>
    
    <?php 
        if(isset($errorMsg[4])) {
            foreach($errorMsg[4] as $emailErrors) {
                echo '<p class="error-msg">'.$emailErrors.'</p>';
            }
        }
    ?>
    <input type="email" name="email" placeholder="Type your email address" value="<?php echo isset($oldInput['email']) ? htmlspecialchars($oldInput['email']) : ''; ?>">
    
    <?php 
        if(isset($errorMsg[5])) {
            foreach($errorMsg[5] as $usernameErrors) {
                echo '<p class="error-msg">'.$usernameErrors.'</p>';
            }
        }
    ?>
    <input type="text" name="username" placeholder="Create username" value="<?php echo isset($oldInput['username']) ? htmlspecialchars($oldInput['username']) : ''; ?>" autocomplete="off">
    
    <?php 
        if(isset($errorMsg[6])) {
            foreach($errorMsg[6] as $passwordErrors) {
                echo '<p class="error-msg">'.$passwordErrors.'</p>';
            }
        }
    ?>
    <input type="password" name="password" placeholder="Create password">
    
    <?php 
        if(isset($errorMsg[7])) {
            foreach($errorMsg[7] as $matchErrors) {
                echo '<p class="error-msg">'.$matchErrors.'</p>';
            }
        }
    ?>
    <?php 
        if(isset($errorMsg[8])) {
            foreach($errorMsg[8] as $termErrors) {
                echo '<p class="error-msg">'.$termErrors.'</p>';
            }
        }
    ?>
    <input type="password" name="retype_password" placeholder="Re-type password">
        <div class="text-white">
            <div class="link-white">
                <label for="terms">I accept the <a href="terms.php">Terms and Conditions</a>.</label>
                <input type="checkbox" name="terms" value="accepted" <?php echo isset($oldInput['terms']) ? 'checked' : ''; ?>>
            </div>
        </div>
    <button type="submit" name="submit" class="contact-btn2">Register</button>
</form>

额外配置建议

  • 给数据库users表的username和email字段添加唯一索引,从数据库层面阻止重复数据写入
  • 登录校验密码时使用password_verify($inputPwd, $dbHashedPwd)方法匹配哈希值,不可直接明文对比
  • 生产环境关闭PHP错误显示,避免泄露数据库敏感信息

内容的提问来源于stack exchange,提问作者Itumeleng Kgosana

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.03 04:01:19