在用户会话中存储用户数据,并在成功注销后保留数据

Storing user data in the user session and retaining data after a successful logout

提问人:smokerswap 提问时间:5/26/2023 最后编辑:smokerswap 更新时间:5/27/2023 访问量:69

问:

将用户配置文件图像存储在用户会话中,并在每个新会话中显示在用户主页上

问题是用户配置文件图像将在首次使用刚刚创建的帐户登录时显示。但是,在用户注销并重新登录后,将不会显示个人资料图像。

好的,在用户注册成功后,我成功地将图像文件名存储到我的数据库中,我也在注册时成功地将配置文件图像存储到我的目录中。但是,我觉得在会话中存储用户个人资料图像时,我没有做正确的事情,因为该图像将在首次登录时显示在主页上,并使用此代码行...

<?php 
    echo $_SESSION['profile_img']; 
?>

在主页中。这是我的注册表单的 PHP,向您展示我如何处理数据。

<?php
include("config.php");

$errors = [];
$successMessage = "";

session_start(); // Start or resume the session

if (isset($_POST["submit"])) {
    // Retrieve form data
    $username = $_POST["username"];
    $email = $_POST["email"];
    $password = $_POST["password"];
    $profile_img = $_FILES["profile_img"]["name"];
    $profile_img_tmp = $_FILES["profile_img"]["tmp_name"];
    $confPassword = $_POST["confPassword"];
    $termsCheck = isset($_POST["termsCheck"]) ? 1 : 0; // Check if checkbox is checked

    // Validate form data
    if (empty($username)) {
        $errors["username"] = "Username is required";
    }

    if (empty($email)) {
        $errors["email"] = "Email is required";
    }

    if (empty($password)) {
        $errors["password"] = "Password is required";
    }

    if ($password !== $confPassword) {
        $errors["confPassword"] = "Passwords do not match";
    }

    if (empty($profile_img)){
        $errors["profile_img"] = "Choose a profile picture";
    }

    if ($termsCheck !== 1) { // Check if checkbox is checked
        $errors["termsCheck"] = "You must agree to the terms and conditions";
    }

    // If there are no validation errors, proceed with registration
    if (count($errors) === 0) {
        // Check if username already exists
        $stmt = mysqli_stmt_init($conn);
        $sql = "SELECT * FROM users WHERE username = ?";
        mysqli_stmt_prepare($stmt, $sql);
        mysqli_stmt_bind_param($stmt, "s", $username);
        mysqli_stmt_execute($stmt);
        $result = mysqli_stmt_get_result($stmt);

        if (mysqli_num_rows($result) > 0) {
            $errors["username"] = "Username already exists";
            $errors["email"] = "Email already exists";
        } else {
            // Check if email already exists
            $stmt = mysqli_stmt_init($conn);
            $sql = "SELECT * FROM users WHERE email = ?";
            mysqli_stmt_prepare($stmt, $sql);
            mysqli_stmt_bind_param($stmt, "s", $email);
            mysqli_stmt_execute($stmt);
            $result = mysqli_stmt_get_result($stmt);

            if (mysqli_num_rows($result) > 0) {
                $errors["email"] = "Email already exists";
            } else {
                $hashedPassword = password_hash($password, PASSWORD_DEFAULT);
                $created = date('Y-m-d H:i:s');
                $uploadDir = "profile_images/"; // Directory to store profile images
                $targetFilePath = $uploadDir . basename($profile_img);

                // Move uploaded file to the target directory
                if (move_uploaded_file($profile_img_tmp, $targetFilePath)) {
                    // File move success
                    $stmt = mysqli_stmt_init($conn);
                    $sql = "INSERT INTO users (username, email, password, profile_img, created_at, terms_agreement) VALUES (?, ?, ?, ?, ?, ?)";
                    mysqli_stmt_prepare($stmt, $sql);
                    mysqli_stmt_bind_param($stmt, "sssssi", $username, $email, $hashedPassword, $targetFilePath, $created, $termsCheck);
                    mysqli_stmt_execute($stmt);

                    $successMessage = "Registration successful! You can now login.";
                    $_POST = array(); // Clear form data

                    // Set profile_img in session
                    $_SESSION['profile_img'] = $targetFilePath;
                } else {
                    // File move failed
                    $errors["profile_img"] = "Error uploading the profile picture";
                }
            }
        }
    }
}
?>

这是我的想法,我相信这个问题也与我的注销功能有关,该功能也处理会话。

这是我主页上的注销功能...

<script>
    function logout() {
        // Send an AJAX request to logout.php
        var xhr = new XMLHttpRequest();
        xhr.open('GET', 'logout.php', true);
        xhr.onreadystatechange = function () {
            if (xhr.readyState === 4 && xhr.status === 200) {
                // Redirect to the login page
                window.location.href = 'login.php';
            }
        };
        xhr.send();
    }
</script>

这是我logout.php......

<?php
    session_start(); // Start the session
    session_destroy(); // Destroy the session

    // Redirect to the login page
    header("Location: login.php");
    exit;
?>

关于如何达到预期效果的任何想法?再说一次,我试图做的是即使在成功注销后仍保留用户会话数据,以便用户下次登录时仍可以看到用户个人资料图像。

(添加了登录页面代码)

<?php
session_start();
include('config.php');

if (isset($_SESSION['username'])) {
    header("location: home.php");
    exit();
}

$username = $password = "";
$name_err = $password_err = "";
$max_login_attempts = 3; // Maximum number of login attempts allowed
$wait_time_minutes = 15; // Time to wait in minutes before allowing login again

if ($_SERVER["REQUEST_METHOD"] == "POST") {
    // Validate username
    if (empty(trim($_POST["username"]))) {
        $name_err = "Please enter your username.";
    } else {
        $username = trim($_POST["username"]);
    }

    // Validate password
    if (empty(trim($_POST["password"]))) {
        $password_err = "Please enter your password.";
    } else {
        $password = trim($_POST["password"]);
    }

    // Check if there are no errors
    if (empty($name_err) && empty($password_err)) {
        // Perform login authentication
        $sql = "SELECT username, password, login_attempts, last_attempt FROM users WHERE username = ?";
        $stmt = $conn->prepare($sql);
        $stmt->bind_param("s", $username);
        $stmt->execute();
        $stmt->store_result();

        if ($stmt->num_rows == 1) {
            $stmt->bind_result($id, $hashed_password, $login_attempts, $last_attempt);
            $stmt->fetch();

            // Check if the user is locked out due to too many login attempts
            if ($login_attempts >= $max_login_attempts) {
                $time_diff = strtotime(date("Y-m-d H:i:s")) - strtotime($last_attempt);
                $minutes_passed = floor($time_diff / 60);

                if ($minutes_passed >= $wait_time_minutes) {
                    // Reset login attempts and last attempt
                    $login_attempts = 0;
                    $last_attempt = null;

                    // Update the user's login details in the database
                    $stmt = $conn->prepare("UPDATE users SET login_attempts = ?, last_attempt = ? WHERE username = ?");
                    $stmt->bind_param("iss", $login_attempts, $last_attempt, $username);
                    $stmt->execute();

                    $stmt->close();
                } else {
                    $password_err = "Too many login attempts. Please try again after $wait_time_minutes minutes.";
                    header("location: login.php?error=too_many_attempts");
                    exit();
                }
            }

            // Verify the password
            if (password_verify($password, $hashed_password)) {
                // Password is correct
                // Reset login attempts and last attempt
                $login_attempts = 0;
                $last_attempt = null;

                // Update the user's login details in the database
                $stmt = $conn->prepare("UPDATE users SET login_attempts = ?, last_attempt = ? WHERE username = ?");
                $stmt->bind_param("iss", $login_attempts, $last_attempt, $username);
                $stmt->execute();

                // Store the username in session
                $_SESSION['username'] = $username;

                // Redirect to the dashboard or another page
                header("location: home.php");
                exit();
            } else {
                // Password is incorrect
                $password_err = "Invalid password.";
                $login_attempts++;
                $last_attempt = date("Y-m-d H:i:s");

                // Update the user's login details in the database
                $stmt = $conn->prepare("UPDATE users SET login_attempts = ?, last_attempt = ? WHERE username = ?");
                $stmt->bind_param("iss", $login_attempts, $last_attempt, $username);
                $stmt->execute();

                header("location: login.php?error=invalid_credentials");
                exit();
            }
        } else {
            $name_err = "Username not found.";
            header("location: login.php?error=username_not_found");
            exit();
        }

        $stmt->close();
    }

    $conn->close();
}
?>
php mysql 数据库 会话 mysqli

评论

2赞 Andrew 5/26/2023
注销后保留用户会话数据是数据库的用途,您试图破坏会话的目的。当用户重新登录时,创建一个新会话,从数据库中选择配置文件图像路径并将其放入新会话中。
0赞 smokerswap 5/26/2023
好的,我明白了,我相信问题是我将用户图像文件名存储到我的数据库中,而不是目录路径。
0赞 smokerswap 5/26/2023
更正,那也不是问题。
0赞 CBroe 5/26/2023
那么现在的问题到底是什么呢?使用“因为图像将在第一次登录时显示在主页上,使用此代码行”,您将其表述为好像这是有效的。
0赞 smokerswap 5/26/2023
它确实有效。用户个人资料图像将在首次登录时显示,但随后在首次注销后登录将不会显示用户个人资料图像。

答:

-1赞 smokerswap 5/27/2023 #1

好吧,我想出了如何纠正这个问题的方法。

我需要添加的只是通过添加这个来存储会话profile_img登录时的行......

$_SESSION['profile_img'] = $profile_img; <----
$_SESSION['username'] = $username;

添加到登录脚本。