PHP Login system not working


#1

Hello, i’m making a Login system using php but it doesn’t fully work yet.
The main errors are that it does not insert anything when I press send, and that i get the warning:
Warning : mysqli_stmt_close() expects parameter 1 to be mysqli_stmt, boolean given in /storage/ssd5/627/5386627/public_html/register.php on line 77

I’m hoping u guys can tell me what is wrong.
My code for the register page:

<!DOCTYPE html>
<?php

$link = mysqli_connect("localhost","id5386627_informatica","XXXxxx","id5386627_infomaticas");
 
if($link === false){
    die("ERROR: Kon niet verbinden. " . mysqli_connect_error());
}

$username = $password = $confirm_password = "";
$username_err = $password_err = $confirm_password_err = "";
$param_username = $username ;

if($_SERVER["REQUEST_METHOD"] == "POST"){
 
    if(empty(trim($_POST["username"]))){
        $username_err = "Voer uw gebruikersnaam in.";
    } else{
        $sql = "SELECT Naam FROM Users WHERE Naam = ?";
        
        if($stmt = mysqli_prepare($link, $sql)){
           mysqli_stmt_bind_param( $stmt, "s", $param_username);

            $param_username = trim($_POST["username"]);
            
            if(mysqli_stmt_execute($stmt)){
                mysqli_stmt_store_result($stmt);
                
                if(mysqli_stmt_num_rows($stmt) == 1){
                    $username_err = "Deze gebruikersnaam is al in gebruik.";
                } else{
                    $username = trim($_POST["username"]);
                }
            } else{
                echo "Er ging iets mis, probeer het later nog een keer.";
            }
        }
         
        mysqli_stmt_close($stmt);
    }
    
    if(empty(trim($_POST["password"]))){
        $password_err = "Voer uw wachtwoord in.";     
    } elseif(strlen(trim($_POST["password"])) < 6){
        $password_err = "Het wachtwoord heeft op zijn minst 6 karakters nodig.";
    } else{
        $password = trim($_POST["password"]);
    }
    
    if(empty(trim($_POST["confirm_password"]))){
        $confirm_password_err = "Voer nogmaals uw wachtwoord in.";     
    } else{
        $confirm_password = trim($_POST["confirm_password"]);
        if(empty($password_err) && ($password != $confirm_password)){
            $confirm_password_err = "Het wachtwoord kwam niet overeen.";
        }
    }
    
    if(empty($username_err) && empty($password_err) && empty($confirm_password_err)){
      
      $param_username = $username;
      $param_password = password_hash($password, PASSWORD_DEFAULT); 
      
        $sql = "INSERT INTO Users (Naam, wachtwoord) VALUES ($param_username, $param_password)";
        
        if($stmt = mysqli_prepare($link, $sql)){
            mysqli_stmt_bind_param($stmt, 'ss' , $param_username, $param_password);
                                    
          if(mysqli_stmt_execute($stmt)){
                header("location: login.php");
              exit;
            } else{
                echo "Er is iets mis gegaan, probeer het later opnieuw.";
            }
        }
         
       mysqli_stmt_close($stmt);    
    }
    mysqli_close($link);
}
?>

  <html>

  <head>
    <meta charset="UTF-8">
    <title>Account aanmaken</title>
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.css">
    
  </head>

    <body>
    <center>
      <style type="text/css">
      body {
        font: 14px sans-serif;
      }

      .wrapper {
        width: 350px;
        padding: 20px;
      }
    </style>
      <div class="wrapper">
        <h2>Account aanmaken</h2>
        <p>Vul de onderstaande dingen in om een account aan te maken!</p>
        <form method="post" action="<?php echo htmlspecialchars($_SERVER['PHP_SELF']); ?>">
          <div class="form-group <?php echo (!empty($username_err)) ? 'has-error' : ''; ?>">
            <label>Naam:</label>
            <input type="text" name="username" class="form-control" value="<?php echo $username; ?>">
            <span class="help-block"><?php echo $username_err; ?></span>
          </div>
          <div class="form-group <?php echo (!empty($password_err)) ? 'has-error' : ''; ?>">
            <label>Wachtwoord:</label>
            <input type="password" name="password" class="form-control" value="<?php echo $password; ?>">
            <span class="help-block"><?php echo $password_err; ?></span>
          </div>
          <div class="form-group <?php echo (!empty($confirm_password_err)) ? 'has-error' : ''; ?>">
            <label>Wachtwoord herhalen:</label>
            <input type="password" name="confirm_password" class="form-control" value="<?php echo $confirm_password; ?>">
            <span class="help-block"><?php echo $confirm_password_err; ?></span>
          </div>
          <div class="form-group">
            <input type="submit" class="btn btn-primary" value="Verzenden">
            <input type="reset" class="btn btn-default" value="Leeg maken">
          </div>
          <p>Heb je al een account? <a href="login.php">log hier in</a>.</p>
        </form>
      </div>
    </center>
  </body>

  </html>

And my code for the login page:

<!DOCTYPE html>
<?php
session_start();

$link = mysqli_connect("localhost","id5386627_informatica","XXXxxx","id5386627_infomaticas");
 
if($link === false){
    die("ERROR: Kon niet verbinden. " . mysqli_connect_error());
}

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

require_once "index.php";
 
$username = $password = "";
$username_err = $password_err = "";
$param_username = $username ; 
$param_password = password_hash($password, PASSWORD_DEFAULT);

if($_SERVER["REQUEST_METHOD"] == "POST"){
 
    if(empty(trim($_POST["username"]))){
        $username_err = "Voer hier uw gebruikersnaam in.";
    } else{
        $username = trim($_POST["username"]);
    }
    
    if(empty(trim($_POST["password"]))){
        $password_err = "Voer uw wachtwoord in.";
    } else{
        $password = trim($_POST["password"]);
    }
    
    if(empty($username_err) && empty($password_err)){
        $sql = "SELECT Naam, wachtwoord FROM Users WHERE Naam = ?";
        
        if($stmt = mysqli_prepare($link, $sql)){
            mysqli_stmt_bind_param($stmt, 's', $param_username);
            
            $param_username = $username;
            
            if(mysqli_stmt_execute($stmt)){
                mysqli_stmt_store_result($stmt);
                
                if(mysqli_stmt_num_rows($stmt) == 1){                    
                    mysqli_stmt_bind_result($stmt, $username, $hashed_password);  
                    if(mysqli_stmt_fetch($stmt)){
                        if(password_verify($password, $param_password)){
                            session_start();
                            
                            $_SESSION["loggedin"] = true;
                            $_SESSION["password"] = $password;
                            $_SESSION["username"] = $username;                            
                            
                            header("location: welkom.php");
                          exit;
                        } else{
                            $password_err = "Het wachtwoord bestaat niet.";
                        }
                    }
                } else{
             $username_err = "Geen account gevonden met deze gebruikersnaam.";
                }
            } else{
                echo "Er is iets misgegaan, probeer het later opnieuw.";
            }
        }
        
        mysqli_stmt_close($stmt);
    }
    
    mysqli_close($link);
}

?>

  <html>

  <head>
    <meta charset="UTF-8">
    <title>Inloggen</title>
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.css">
    <style type="text/css">
      body {
        font: 14px sans-serif;
      }

      .wrapper {
        width: 350px;
        padding: 20px;
      }
    </style>
  </head>

  <body>
    <center>
      <div class="wrapper">
        <h2>Login</h2>
        <p>Voer uw gegevens in om door te gaan.</p>
        <form method="post" action="<?php echo htmlspecialchars($_SERVER['PHP_SELF']); ?>">
          <div class="form-group <?php echo (!empty($username_err)) ? 'has-error' : ''; ?>">
            <label>Gebruikersnaam</label>
            <input type="text" name="username" class="form-control" value="<?php echo $username; ?>">
            <span class="help-block"><?php echo $username_err; ?></span>
          </div>
          <div class="form-group <?php echo (!empty($password_err)) ? 'has-error' : ''; ?>">
            <label>Wachtwoord</label>
            <input type="password" name="password" class="form-control">
            <span class="help-block"><?php echo $password_err; ?></span>
          </div>
          <div class="form-group">
            <input id="button" type="submit" class="btn btn-primary" value="Verzenden">
            <input id="button" type="reset" class="btn btn-default" value="Leeg maken">
          </div>
          <p>Heb je nog geen account? <a href="register.php">Meld je hier aan</a>.</p>
        </form>
      </div>
    </center>
  </body>

  </html>

Thanks!


#2

The error is coming from here:

if($stmt = mysqli_prepare($link, $sql)){
}
mysqli_stmt_close($stmt);

If the prepare fails for some reason then false is returned which in turn causes the close to fail. As a rule there is really no need to close statements. I don’t recall ever seeing it used before. In any event, move the close statements up inside the bracket (or just delete it) and then figure out why the prepare is failing. Something in your sql probably.


#3

I’m a bit confused about the password-checking logic in the second piece of code. At the start, you do this:

$username = $password = "";
...
$param_password = password_hash($password, PASSWORD_DEFAULT);

As $password is blank at this point, what is the idea of creating $param_password from it?

Then you set $password to the value of the user input, but a bit later you do this:

mysqli_stmt_bind_result($stmt, $username, $hashed_password);  
if(mysqli_stmt_fetch($stmt)){
  if(password_verify($password, $param_password)){

Shouldn’t you be comparing with $hashed_password (from the database) rather than $param_password here?

And this bit

$_SESSION["username"] = $username;                            

is a bit of a security no-no, don’t keep unhashed passwords in something like a session variable.

ETA - in the first bit of code:

$sql = "INSERT INTO Users (Naam, wachtwoord) VALUES ($param_username, $param_password)";
        
if($stmt = mysqli_prepare($link, $sql)){
  mysqli_stmt_bind_param($stmt, 'ss' , $param_username, $param_password);                                  

I don’t do much mysqli, but that doesn’t look like a valid query to me as @ahundiak alluded to. I would have thought it might allow you to prepare the query even without any parameters, so maybe that’s not causing you an error, but the following lines suggest it is not what you intended.


#4

What should I change in the first bit of code to make it work then @droopsnoot?

Thanks for the reply though!


#5

Actually, it’s just empty at the beginning, but gets overwritten here.

This means that the password is ok at this point and isn’t being used until a few lines down.

$sql = "INSERT INTO Users (Naam, wachtwoord) VALUES ($param_username, $param_password)";

As to this line, I think that’s what’s causing the problem. It’s being improperly implemented. Since the OP is using prepared statements, they are required to use placeholders in the query. The equivalent of this situation in PDO is this error.

Warning: PDOStatement::execute(): SQLSTATE[HY093]: Invalid parameter number: number of bound variables does not match number of tokens in

Don’t close the connection manually. Let PHP do this. You may want to do more database work later so closing the connection and reopening it every time you want to do a database call is very inefficient. Just let the connection stay opened and do everything you want with the database. Then let PHP close it by itself.


#6

What placeholders should I use in de query?
Your reply is very helpful!


#7

Replace all of your variables you have put in the query and replace them with ?.


#8
if(mysqli_stmt_execute($stmt)){
                header("location: login.php");
              exit;
            } else{
                echo "Er is iets mis gegaan, probeer het later opnieuw.";
            }

When I replace the variables in the query with ?, I get this echo from the else which says “Something went wrong, try again later.” So if I use the placeholders the If above does not work anymore?


#9

Can we get screenshots of what you are seeing? And also, please remove both the mysqli_stmt_close($stmt); and mysqli_close($link); lines. That’s what’s causing your original error.


This is also incorrect. $param_password is coming from an empty string you hashed. I believe this is what @droopsnoot maybe talking about. You need to use $hashed_password instead of $param_password. Then remove $param_password completely because there is no legit use for it.


#10

In the upper left corner you can see the echo


#11

Yes, I deleted both, thanks for that @droopsnoot and @spaceshiptrooper!


#12

What about the code you have? Does it look like this?

$sql = "INSERT INTO Users (Naam, wachtwoord) VALUES (?, ?)";

This is the correct way of doing it because you have 2 columns you want to insert data into. So you are required to use 2 ?.


#13

Yes, that exact query is in my code, but I still get that echo


#14

Can we get a screenshot of just the table rows in your database? Don’t take a capture of the URL.


#15


#16

This is what I’m seeing. I used very minimum changes and got yours to work. Not entirely sure why you can’t get it to work. Are you just using codeanywhere to code your files?


#17

Yes, I only use codeanywhere, but your code is almost exactly the same as mine and yours works. Wierd


#18

I have no idea either. I tried to replicate the problem, but it seems to just insert perfectly for me. Even on 000webhost. Are you sure there isn’t something you missed or updated? Can you post the full code you have currently to here? Please wrap the codes using the </> icon as well.


#19

Well, it is as it is.
But I have another question actually, if I go to the login screen, and I log in with the name and password that are in the database, I don’t get forwarded to the welkom.php, but I get forwarded to a page that says login.php but has everything of the index.php in it.
Can you maybe help @spaceshiptrooper?
My code:

<!DOCTYPE html>
<?php
//session_start();

$link = mysqli_connect("localhost","id5386627_root","XXXxxx","id5386627_root");
 
if($link === false){
    die("ERROR: Kon niet verbinden. " . mysqli_connect_error());
}

if(isset($_SESSION["loggedin"]) && $_SESSION["loggedin"] === true){
    header("location: welkom.php");
    exit;
}
 
$username = $password = "";
$username_err = $password_err = "";
$param_username = $username ; 
$param_password = password_hash($password, PASSWORD_DEFAULT);

if($_SERVER["REQUEST_METHOD"] == "POST"){
 
    if(empty(trim($_POST["username"]))){
        $username_err = "Voer hier uw gebruikersnaam in.";
    } else{
        $username = trim($_POST["username"]);
    }
    
    if(empty(trim($_POST["password"]))){
        $password_err = "Voer uw wachtwoord in.";
    } else{
        $password = trim($_POST["password"]);
    }
    
    if(empty($username_err) && empty($password_err)){
        $sql = "SELECT Naam, wachtwoord FROM Users WHERE Naam = ?";
        
        if($stmt = mysqli_prepare($link, $sql)){
            mysqli_stmt_bind_param($stmt, 's', $param_username);
            
            $param_username = $username;
            
            if(mysqli_stmt_execute($stmt)){
                mysqli_stmt_store_result($stmt);
                
                if(mysqli_stmt_num_rows($stmt) == 1){                    
                    mysqli_stmt_bind_result($stmt, $username, $hashed_password);  
                    if(mysqli_stmt_fetch($stmt)){
                        if(password_verify($password, $hashed_password)){
                            session_start();
                            
                            $_SESSION["loggedin"] = true;
                            $_SESSION["password"] = $password;
                            $_SESSION["username"] = $username;                            
                            
                            header("location: welkom.php");
                          exit;
                        } else{
                            $password_err = "Het wachtwoord bestaat niet.";
                        }
                    }
                } else{
             $username_err = "Geen account gevonden met deze gebruikersnaam.";
                }
            } else{
                echo "Er is iets misgegaan, probeer het later opnieuw.";
            }
        }
        
  
    }
    
 
}

?>

  <html>

  <head>
    <meta charset="UTF-8">
    <title>Inloggen</title>
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.css">
    <style type="text/css">
      body {
        font: 14px sans-serif;
      }

      .wrapper {
        width: 350px;
        padding: 20px;
      }
    </style>
  </head>

  <body>
    <center>
      <div class="wrapper">
        <h2>Login</h2>
        <p>Voer uw gegevens in om door te gaan.</p>
        <form method="post" action="<?php echo htmlspecialchars($_SERVER['PHP_SELF']); ?>">
          <div class="form-group <?php echo (!empty($username_err)) ? 'has-error' : ''; ?>">
            <label>Gebruikersnaam</label>
            <input type="text" name="username" class="form-control" value="<?php echo $username; ?>">
            <span class="help-block"><?php echo $username_err; ?></span>
          </div>
          <div class="form-group <?php echo (!empty($password_err)) ? 'has-error' : ''; ?>">
            <label>Wachtwoord</label>
            <input type="password" name="password" class="form-control">
            <span class="help-block"><?php echo $password_err; ?></span>
          </div>
          <div class="form-group">
            <input id="button" type="submit" class="btn btn-primary" value="Verzenden">
            <input id="button" type="reset" class="btn btn-default" value="Leeg maken">
          </div>
          <p>Heb je nog geen account? <a href="register.php">Meld je hier aan</a>.</p>
        </form>
      </div>
    </center>
  </body>

  </html>

#20

Hi, @1000prosent, I’ve reformatted your code for you, because the single backtick before and after only work for inline code. For larger blocks of code, you need to place three (3) backticks on the line before the code, and three backticks on the line after the code.