繁体   English   中英

什么可能导致 PHP 插入 MYSQL 数据库错误地将来自另一个用户的数据插入一行?

[英]What could cause a PHP insert into a MYSQL database to wrongly insert data from another user into a row?

我的一个学生正在将她的学习游戏分数保存到 MySQL 数据库中,但不知何故,另一个人的名字最终存储在她的数据库行中。 这怎么可能? 这是插入的 PHP。

// Get Configuration file
require "configenzymatic.php";

// Connect to your server

$dbh = new PDO("mysql:host=$host;dbname=$dbname;charset=utf8", $user, $pass, array(PDO::MYSQL_ATTR_FOUND_ROWS => true));

$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);

///////////////////////////////////////////////////////
// Status Checker
///////////////////////////////////////////////////////
if ($_GET["status"]) {
    echo "online";
    exit;
}

///////////////////////////////////////////////////////
// Upload new score
///////////////////////////////////////////////////////

//set POST data as data to be checked and updated
$firstname = $_POST['firstname'];
$lastname = $_POST['lastname'];
$email = $_POST['email'];
$password = $_POST['password'];
$level1right = $_POST['level1right'];
$level1wrong = $_POST['level1wrong'];
$level2right = $_POST['level2right'];
$level2wrong = $_POST['level2wrong'];
$level3right = $_POST['level3right'];
$level3wrong = $_POST['level3wrong'];
$level4right = $_POST['level4right'];
$level4wrong = $_POST['level4wrong'];

// check for email and set hash variable
$stm = $dbh->prepare("SELECT * FROM $tname WHERE email=?");
$stm->bindValue(1, $email, PDO::PARAM_STR);
$stm->execute();

while ($row = $stm->fetch(PDO::FETCH_ASSOC)) {
    $hashes = array($row['hash']);
    $hash = $row['hash'];
    $id = $row['id'];
    foreach ($hashes as $hash) {
        // If hash matches password, then...

        if (password_verify($password, $hash)) {
            // Everything is cool -- Insert the data into the database (update)

            $stmt = $dbh->prepare("
UPDATE $tname 
   SET firstname = :firstname
     , lastname = :lastname
     ,  hash = :hash
     , level1right = :level1right
     , level1wrong = :level1wrong
     , level2right = :level2right
     , level2wrong = :level2wrong
     , level3right = :level3right
     , level3wrong = :level3wrong
     , level4right = :level4right
     , level4wrong = :level4wrong 
 WHERE email = :email 
   AND id = :id");
            $stmt->execute(array($firstname, $lastname, $hash, $level1right, $level1wrong, $level2right, $level2wrong, $level3right, $level3wrong, $level4right, $level4wrong, $email, $id));
            $affected_rows = $stmt->rowCount();

            // check if row inserted

            /* Return number of rows that were updated */
            $count = $stmt->rowCount();
            echo "$count";
        }
    }
}

学生输入了她的名字,但插入了其他人的名字。 我对此完全感到困惑。 有谁知道这是怎么发生的? 今天 12:30:44 插入姓名代替我学生添加的数据的人,我的学生在 13:44:15 添加了她的数据。 这些数据是如何混合起来的?

我不确定您为什么将更新包装在多个循环中,但是完全有可能存在具有相同密码 hash 的用户,并且(我认为)可以解释您所看到的行为。

您大概是希望使用表单中提交的 email 和密码更新单个用户? 我假设您对表也有限制,以确保 email 地址是唯一的。 因此,您正在获取与 email 匹配的单个用户,并检查他们的密码。 如果匹配,则使用相同的数据库 ID 更新单个记录。 没有循环!

// get password hash
$stm = $dbh->prepare("SELECT id, hash FROM $tname WHERE email=?");
$stm->execute([$_POST["email"]]);

$row  = $stm->fetch(PDO::FETCH_ASSOC);
$hash = $row['hash'];
$id   = $row['id'];
if (!password_verify($_POST["password"], $hash)) {
    // verification failed, do something to present an error to the user
    die();
}
$stmt = $dbh->prepare(
    "UPDATE $tname
        SET firstname=:firstname, lastname=:lastname,
            level1right=:level1right, level1wrong=:level1wrong,
            level2right=:level2right, level2wrong=:level2wrong,
            level3right=:level3right, level3wrong=:level3wrong,
            level4right=:level4right, level4wrong=:level4wrong
        WHERE id=:id"
);
$stmt->execute([
    ":firstname"   => $_POST["firstname"],
    ":lastname"    => $_POST["lastname"],
    ":level1right" => $_POST["level1right"],
    ":level1wrong" => $_POST["level1wrong"],
    ":level2right" => $_POST["level2right"],
    ":level2wrong" => $_POST["level2wrong"],
    ":level3right" => $_POST["level3right"],
    ":level3wrong" => $_POST["level3wrong"],
    ":level4right" => $_POST["level4right"],
    ":level4wrong" => $_POST["level4wrong"],
    ":id"          => $id
]);
$count = $stmt->rowCount();
echo "$count";

另请注意,在 PDO 中使用命名参数需要使用关联数组。 如果没有它,不确定您的原始代码将如何更新任何内容。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM