Search code examples
phpmysqldatabasesessionmysqli

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


Storing user profile image in user session and display on the users home page with every new session

The issue is that the user profile image will display with the first login with an account that was just created. But after the user logs out and logs back in the profile image will not display.

Okay, so I've successfully stored the image file name into my database upon successful user registration, I've also successfully stored the profile image into my directory upon registration. However I feel as though I didn't do something correct when it comes to storing the users profile image within the session because the image will display on the home page on the first login with this line of code...

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

in the home page. Here is the PHP for my registration form to show you how I'm handling the data.

<?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";
                }
            }
        }
    }
}
?>

Here's my thoughts, I believe that this issue has something to do with my logout function that handles the session as well.

Here is the logout function in my home page...

<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>

And here is my logout.php...

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

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

Any thoughts on how I can achieve the desired effect? And again, what I'm trying to do is retain the user session data even after successfully logging out so that the users profile image will still be visible to the user the next time that they login.

(ADDED LOGIN PAGE CODE)

<?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();
}
?>

Solution

  • Well, I figured out how to correct the issue..

    All I needed to add was the line that stores the session profile_img upon logging in by adding this...

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

    to the login script.