Php 如何修复我的多用户登录系统

Php 如何修复我的多用户登录系统,php,mysql,procedural,Php,Mysql,Procedural,你好,我已经遇到这个错误很长时间了。 基本上,这里是代码: function loginUser($conn, $username, $password) { $checkExists = checkExists($conn, $username, $username); if ($checkExists === false) { header("Location: ../login.php?error=wronglogininfo");

你好,我已经遇到这个错误很长时间了。 基本上,这里是代码:

function loginUser($conn, $username, $password) {
    $checkExists = checkExists($conn, $username, $username);

    if ($checkExists === false) {
        header("Location: ../login.php?error=wronglogininfo");
        exit();
    }

    $passwordHashed = $checkExists['password'];
    $checkPassword = password_verify($password, $passwordHashed);

    if ($checkPassword === false) {
        header("Location: ../login.php?error=wronglogin");
        exit();
    } elseif ($checkPassword === true) {
        $query = "SELECT * FROM users WHERE username='$username' AND password='$checkPassword'";
        $query_run = mysqli_query($conn, $query);
        $usertypes = mysqli_fetch_array($query_run);

        if ($usertypes['usertype'] == "admin") {
            header('Location: ../login.php?admin');
        } elseif ($usertypes['usertype'] == "user") {
            header('Location: ../login.php?user');
        }
    }
}

function checkExists($conn, $username, $email) {
    $sql = "SELECT * FROM users WHERE username = ? OR email = ?;";
    $stmt = mysqli_stmt_init($conn);

    if (!mysqli_stmt_prepare($stmt, $sql)) {
        header("Location: ../register.php?error=stmtfailed");
        exit();
    } 

    mysqli_stmt_bind_param($stmt, "ss", $username, $email);
    mysqli_stmt_execute($stmt);

    $resultData = mysqli_stmt_get_result($stmt);

    if ($row = mysqli_fetch_assoc($resultData)) {
        return $row;
    } else {
        $result = false;
        return $result;
    }
    
    mysqli_stmt_close($stmt);
}
因此,这些错误可以正常工作。 真正的问题是,每当我使用正确的凭据登录时,它会将我发送到一个404页面,其中包含一个我从未放置过的目录。我想把它发送到管理面板或用户页面。有人能帮忙吗


这个选择看起来像一条毁灭之路:从用户那里选择* username='$username'和password='$checkPassword'如果$checkPassword 是密码验证()的结果。。(也要注意可能发生的情况 SQL注入。)

我怀疑这是你的主要问题。这将基本上将您的查询转换为:

从用户名为'tony'和密码为'1'的用户中选择*

这可能会返回一个空的结果集,但下一个if语句需要一个填充了数据的用户数组

if ($usertypes['usertype'] == "admin") {
    header('Location: ../login.php?admin');
} elseif ($usertypes['usertype'] == "user") {
    header('Location: ../login.php?user');
}
现在发生了什么?您不会被重定向到任何地方,当前脚本将继续处理。那你能做什么呢

如果您已经有用户行,请通过checkExists()(这可能是 命名更好?),为什么要再次调用数据库以获取 用户类型

您已经可以访问您的用户数组,因为您在上面调用了
checkExists
,并验证它不是false。直接使用数组即可

我只是稍微整理了一下你的代码并添加了一些注释。我没有以任何方式更改您的查询,也没有验证它们是否正确

function loginUser($conn, $username, $password) {

    // Renamed this variable
    // Validate it and use this variable for the remainder of the function.
    $user = checkExists($conn, $username, $username);

    if ($user === false) {
        header("Location: ../login.php?error=wronglogininfo");
        exit();
    }

    $passwordHashed = $user['password'];

    // Renamed this variable.
    $validPassword = password_verify($password, $passwordHashed);

    if ($validPassword === false) {
        header("Location: ../login.php?error=wronglogin");
        exit();
    }
    
    // You now know you have a user and a valid password. 
    // No need to select them again

    if ($user['usertype'] == "admin") {
        header('Location: ../login.php?admin');
        exit;
    } 

    if ($user['usertype'] == "user") {
        header('Location: ../login.php?user');
        exit;
    }

    // What happens if `usertype` not matched? You still need to handle this case?
}

function checkExists($conn, $username, $email) {
    $sql = "SELECT * FROM users WHERE username = ? OR email = ?;";
    $stmt = mysqli_stmt_init($conn);

    if (!mysqli_stmt_prepare($stmt, $sql)) {
        header("Location: ../register.php?error=stmtfailed");
        exit();
    } 

    mysqli_stmt_bind_param($stmt, "ss", $username, $email);
    mysqli_stmt_execute($stmt);

    $resultData = mysqli_stmt_get_result($stmt);

    // Cleaned up this if statement
    if ($row = mysqli_fetch_assoc($resultData)) {
        return $row;
    }
   
    return false;   
}

这个选择看起来像是一条毁灭之路:
select*来自username='$username'和password='$checkPassword'
的用户,如果
$checkPassword
密码验证()的结果。(也要注意可能的SQL注入。)我知道我只是一个php新手,所以我将在稍后添加SQL注入安全性,只是尝试实际获取代码查找。那么我将如何更改我的选择?它会将您发送到哪里?登录页面中是否有我们看不到的东西正在执行另一个重定向?没有实际代码没有问题我知道函数中有问题,因为这个错误以前发生过,错误在函数中,我修复了这个错误。如果你想看这里,它是:好的捕获。删除了它,它与调用之前返回的原始代码具有相同的净效果。哦,我的上帝,非常感谢你们帮助我!还感谢您指出,如果usertype不是admin和user(除非出现错误,否则很可能不会发生,因为我只能将其设置为这两种类型)。@Lunar-那么,是哪一部分导致了您的错误?我必须添加出口,如果问题得到解决,可能不需要使用其他出口;)