How to set up a login session through PHP, MySQL and HTML

At which point? In the beginning when you check to see if the loggedin flag is set, or after your user has logged in?

Don’t forget you need an exit() after your header redirect. You don’t have that after the second one.

Also, is the form at the end of your html the one you use to log in with? Your PHP code does stuff with “username” and “password” fields, but your form has “email” and “password” fields, neither of which have a “name” parameter on them. As your form tag doesn’t specify it, your form fields will be sent in the $_GET array, and yet you look in the $_POST array for the values, or you would if the code got there, which it won’t because you (correctly) check for the REQUEST_METHOD before you get there.

Or do you have some JavaScript that processes the form input and alters those names?

It’s after the user logs in. When Login is clicked, it reloads the page and doesn’t load the database page (aka homepage/index.php)

I’ve added this in. Thanks for the heads up. (But why is this needed? I’m assuming the exit(); function tells PHP to stop processing at that point?)

So, I’m using a template that I found online to build the application. Yes, the login form you see from the code in my previous response is the login form used to login through the database which (if matched correctly), loads the homepage. The HTML in the login code is all my template, not stuff I have written. I need help to figure out what it is I have to rewrite in order to make the login work successfully. I have no JavaScript aid in this code at all other than the database on the homepage (which is not being used on the login page). I am solely relying on PHP unless there is an easier workaround through JavaScript.

Because my form inputs will be sent in $_GET rather than $_POST, does that mean that I need to change every instance of $_POST to $_GET?

Well, you could, but I would add method="post" to the form tag instead.

You need to add name= tags to the form inputs for a start, to match the names you use in your PHP code. Use var_dump($_POST) to see that what is coming into the PHP is correct.

Exactly that. If you don’t exit, PHP will carry on with the rest of the code, which you don’t need it to do. You already had it after your other redirect.

I’ve added the name tags in the form inputs:

<div class="form-group">
                      <input type="email" class="form-control form-control-user" name="username" id="exampleInputEmail" aria-describedby="emailHelp" placeholder="Username">
                    </div>
                    <div class="form-group">
                      <input type="password" class="form-control form-control-user" name="password" id="exampleInputPassword" placeholder="Password">
                    </div>

And the post method to the form tag:

<form class="user" method="post">

How do you run var_dump(_POST) to see if the output is correct? Could I do this from my browser’s console or do I have to write this in my login PHP somewhere?

This. Just put it at the start of your PHP code, inside your check for server-request-method. You could stick an exit() after it, until you see that the values are correct.

I can’t see the output of var_dump($_POST);

How do I see it?

I put it under the server request method:

if($_SERVER["REQUEST_METHOD"] == "POST"){
 
    // VAR_DUMP
	var_dump($_POST);
	exit();

That should do it. Does the code exit at that point, or does it re-draw your form? If it re-draws the form, it’s not hitting the exit, which suggests that the request method is not correct.

I’m not sure. I put an exit there, but it keeps reloading the page and nothing else happens.

Oh, hang on a minute.

<a href="index.php" class="btn btn-primary btn-user btn-block" style="background-color:#a40000; border-color:#a40000;">
Login
</a>

Is this your login button? You need an <input type = "submit"> here, not an a href.

I changed that as you mentioned, but how will the code know where to redirect the user after login?

Also, what is var_dump($_POST) supposed to show me? I don’t see anything, it just keeps refreshing.

That’s normally in the action= parameter in your form tag. If you leave it out, or leave it blank, it will reload the same page using the method you specify.

It’s supposed to show you the contents of whatever you type into the boxes in your form. Well, it shows you the contents of whatever variable you specify, but in this case it’s the `$_POST array which is where your form vars are passed through.

I see. Well, I’ve added the action="index.php" attribute in the form tag and added a value to the submit button, so now my code is this:

<?php

// Initialize the session
session_start();
 
// Check if the user is already logged in, if yes then redirect him to database
if(isset($_SESSION["loggedin"]) && $_SESSION["loggedin"] === true){
    header("location: index.php");
    exit;
}
 
// Include config file
require_once "api/dbconnect.php";
 
// Define variables and initialize with empty values
$username = $password = "";
$username_err = $password_err = "";
 
// Processing form data when form is submitted
if($_SERVER["REQUEST_METHOD"] == "POST"){
 
    // VAR_DUMP
	var_dump($_POST);
	exit();
	
	// Check if username is empty
    if(empty(trim($_POST["username"]))){
        $username_err = "Please enter username.";
    } else{
        $username = trim($_POST["username"]);
    }
    
    // Check if password is empty
    if(empty(trim($_POST["password"]))){
        $password_err = "Please enter your password.";
    } else{
        $password = trim($_POST["password"]);
    }
    
    // Validate credentials
    if(empty($username_err) && empty($password_err)){
        // Prepare a select statement
        $sql = "SELECT id, username, password FROM admins WHERE username = :username";
        
        if($stmt = $pdo->prepare($sql)){
            // Bind variables to the prepared statement as parameters
            $stmt->bindParam(":username", $param_username, PDO::PARAM_STR);
            
            // Set parameters
            $param_username = trim($_POST["username"]);
            
            // Attempt to execute the prepared statement
            if($stmt->execute()){
                // Check if username exists, if yes then verify password
                if($stmt->rowCount() == 1){
                    if($row = $stmt->fetch()){
                        $id = $row["id"];
                        $username = $row["username"];
                        $hashed_password = $row["password"];
                        if(password_verify($password, $hashed_password)){
                            // Password is correct, so start a new session
                            session_start();
                            
                            // Store data in session variables
                            $_SESSION["loggedin"] = true;
                            $_SESSION["id"] = $id;
                            $_SESSION["username"] = $username;                            
                            
                            // Redirect user to welcome page
                            header("location: index.php");
							exit();
                        } else{
                            // Display an error message if password is not valid
                            $password_err = "The password you entered was not valid.";
                        }
                    }
                } else{
                    // Display an error message if username doesn't exist
                    $username_err = "No account found with that username.";
                }
            } else{
                echo "Something went wrong. Please try again later.";
            }
        }
        
        // Close statement
        unset($stmt);
    }
    
    // Close connection
    unset($pdo);
}
?>

<!DOCTYPE html>
<html lang="en">

<head>

  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
  <meta name="description" content="">
  <meta name="author" content="">

  <title>CCRP - Database Login</title>

  <!-- Custom fonts for this template-->
  <link href="vendor/fontawesome-free/css/all.min.css" rel="stylesheet" type="text/css">
  <link href="https://fonts.googleapis.com/css?family=Nunito:200,200i,300,300i,400,400i,600,600i,700,700i,800,800i,900,900i" rel="stylesheet">

  <!-- Custom styles for this template-->
  <link href="css/sb-admin-2.min.css" rel="stylesheet">

</head>

<body class="bg-gradient-primary">

  <div class="container">

    <!-- Outer Row -->
    <div class="row justify-content-center">

      <div class="col-xl-10 col-lg-12 col-md-9">

        <div class="card o-hidden border-0 shadow-lg my-5">
          <div class="card-body p-0">
            <!-- Nested Row within Card Body -->
            <div class="row">
              <div class="col-lg-6 d-none d-lg-block"><img src="img/rpwall.jpg" width="485" height="600"></div>
              <div class="col-lg-6">
                <div class="p-5">
                  <div class="text-center">
                    <h1 class="h4 text-gray-900 mb-4">Welcome</h1>
                  </div>
                  <form class="user" method="post" action="index.php">
                    <div class="form-group">
                      <input type="text" class="form-control form-control-user" name="username" id="exampleInputEmail" aria-describedby="emailHelp" placeholder="Username">
                    </div>
                    <div class="form-group">
                      <input type="password" class="form-control form-control-user" name="password" id="exampleInputPassword" placeholder="Password">
                    </div>
                    <div class="form-group">
                      <div class="custom-control custom-checkbox small">
                        <input type="checkbox" class="custom-control-input" id="customCheck">
                        <!-- <label class="custom-control-label" for="customCheck">Remember Me</label> -->
                      </div>
                    </div>
                    <input type="submit" class="btn btn-primary btn-user btn-block" style="background-color:#a40000; border-color:#a40000;" value="Login">
                    <hr>
                    <!-- <a href="index.html" class="btn btn-google btn-user btn-block">
                      <i class="fab fa-google fa-fw"></i> Login with Google
                    </a>
                    <a href="index.html" class="btn btn-facebook btn-user btn-block">
                      <i class="fab fa-facebook-f fa-fw"></i> Login with Facebook
                    </a> -->
                  </form>
                  <div class="text-center">
                    <a class="small" href="forgot-password.php">Reset Password</a>
                  </div>
                  <div class="text-center">
                    <a class="small" href="register.php">Create a Database Account</a>
                  </div>
                </div>
              </div>
            </div>
          </div>
        </div>

      </div>

    </div>

  </div>

  <!-- Bootstrap core JavaScript-->
  <script src="vendor/jquery/jquery.min.js"></script>
  <script src="vendor/bootstrap/js/bootstrap.bundle.min.js"></script>

  <!-- Core plugin JavaScript-->
  <script src="vendor/jquery-easing/jquery.easing.min.js"></script>

  <!-- Custom scripts for all pages-->
  <script src="js/sb-admin-2.min.js"></script>

</body>

</html>

But no login session is being made nor do I see var_dump output.

Well, I don’t get it. Are you saying that it doesn’t execute the var_dump() and exit() statements? If so, that means that it’s not getting into that if clause, which means there must be something else at work.

Is it live anywhere, where someone could actually see it running? There is too much that I don’t have (all the linked JS stuff) for me to put it on my test machine.

No, it is only live on my local machine. I am not ready for deployment yet.

I don’t believe it is executing because there is another if statement above it:

if(isset($_SESSION["loggedin"]) && $_SESSION["loggedin"] === true){
    header("location: index.php");
    exit;
}

This is supposed to check if there an active session. If there is, it’ll redirect to the database.

What is the name of the file containing the code that you are working on here? Isn’t that index.php? I thought that’s why you put it in the “action” parameter for your form.

If it is, then your check above is just going to redirect to the same place over and over. Except that if the login code isn’t working in the first place, you’ll never be able to set that session var, so it won’t redirect.

If it is not, then your form action needs to point back to this file, as this file contains the form processing code.

The file containing the code above is login.php. If a user logs in successfully, it should create a session and redirect to index.php where the database is located.

I added the action tag to index.php as I thought that’s what was needed in order to complete the redirect.

I changed it back to login.php. and here is what I receive:

array(2) { ["username"]=> string(5) "Test1" ["password"]=> string(9) "TestUser1" }

This must be the var_dump($_POST) output. (I actually did type test user credentials for privacy, so these are not real credentials)

However, when I type in the real credentials in the form to login, the page still reloads.

So, when you tested with real credentials, did you remove the var_dump and exit statements?

As you’ve now got it going into the section that reads from the database, you can add echo and exit pairs past each section, and see how far it gets.

I notice you set various error messages through the login process, but I can’t see that you display them anywhere. You have an echo to say something went wrong, but you probably won’t see that because it’s before your DOCTYPE and opening html tag.

I did try with real credentials and I commented out the var_dump and exit() lines to no effect. The page still reloads.

I do not display error messages yet because I need to figure out how the template displays them (as far as css classes and etc.) According to the code they provided, it doesn’t look like they are being displayed anywhere.

No, no, no. Get it working first, then make it look nice.

Yes, but that’s after it’s tried to read and verify the login information that you provided for sign-in. But because you don’t show your error messages, or even just exit out when you hit a problem (during dev only, of course), you don’t know how far through it does get.

1 Like

For now, just add an exit after each line that assigns an error message. Then you can see where it goes over.

Is your password column big enough to store a hashed password?