1

I am trying to create a login page for my website. I copied and pasted this from another site I built where the login works just fine. I used the echo statement to test it, but all I am getting when I try to log in is a cut off version of the login page. It cuts off right at the point where this code is pasted into the HTML code. I've looked over it so many times my eyes have gone cross-eyes, so I'm not sure what I'm missing! Any help is much appreciated!

<?php
                    if($_SERVER['REQUEST_METHOD'] != 'POST') {
                        echo '<form method="post" action="">
                        <p><label for="username">Username:</label><input type="text" name="username" id="username" title="username"></p>
                        <p><label for="password">Password:</label><input type="password" name="password" id="password" title="password"></p>
                        <p><input type="submit" name="login" id="login" value="Login"></p></form>';
                    } else {
                        $username = $_POST['username'];
                        $password = $_POST['password'];

                        $mysqli = new mysqli("","","","");
                        if($mysqli->connect_error) {
                            exit('Error connecting to database');
                        } else {
                            $sql2 = "SELECT admin_id, admin_username, admin_password FROM adminlogin WHERE admin_username = ?";
                            if(($stmt = $mysqli->prepare($sql2)) === false) {
                                error_log($mysqli->error);
                                error_log("SQL = [$sql2]");
                                die("Database error, contact site admin");
                            } else {
                                $stmt->bind_param("s", $username);
                                $stmt->execute();
                                $stmt->store_result();
                                if($stmt->store_result() === false) {
                                    error_log($stmt->error);
                                    die("Database error, contact site admin.");
                                } else {
                                    echo 'No error';
                                }// test store
                            } // bind param
                        } // sql statement
                    } // test connection
                    ?>
                </div>
                <div class="col-1-3">
                    <h2>Search Blog</h2><br>
                    <form method="post" action="search.php" name="search" id="search">
                        <p><input type="text" name="searchinput" id="searchinput" title="search"></p>
                        <p><input type="submit" name="search" id="search" value="Search"></p>
                    </form>
                    <br>
                    <h2>About</h2>
                    <p>Hello and welcome to Cooking for Alaska: THM and Healthy Eating on a Budget! It is my prayer that you will find this blog useful in helping your family eat healthy while living on an Alaska-based budget. Groceries in Alaska are expensive, but feeding your family shouldn't be! Please enjoy my blog and feel free to contact me with any questions.</p>
                    <br>
                    <h2>Recent Blog Posts</h2>
                    <?php
                    include('includes/dblogin.php');
                    $sql = "SELECT * FROM recentposts_short ORDER BY post_datetime DESC LIMIT 3";
                    $result = mysqli_query($con, $sql);
                    if($result == false) {
                        $mysql_error = mysqli_error($con);
                        echo '<p>There was an error. Please contact an administrator.</p>';
                    } else {
                        while($row=mysqli_fetch_assoc($result)) {
                            echo '<p><bold><a href="blog.php?id='.$row['post_title'].'">'.$row['post_title'].'</a></bold></p>';
                            echo '<p class="smallfont">'.$row['post_datetime'].'</p><br>';
                        }
                    }
                    ?><br>
Dharman
  • 30,962
  • 25
  • 85
  • 135
jacdevelop
  • 13
  • 5
  • Maybe there is no row in your database for the username you enter? That would make your `while($stmt->fetch())` loop execute zero times, and it appears that there is no output to indicate an unknown user. – Bill Karwin Feb 08 '20 at 19:07
  • By the way, you should probably change your mysql admin password now that you've posted it on the internet. – Bill Karwin Feb 08 '20 at 19:07
  • There is a row for the username. I double checked that. And yes, I changed the password, but thank you for the extra heads up! – jacdevelop Feb 08 '20 at 22:17
  • My strategy at this point would be to add several lines of code at each step to call `error_log()` to output information about what has been done successfully. Then watch your http server error log for that output. This is a common debugging technique for PHP. – Bill Karwin Feb 09 '20 at 02:12
  • I got as far as the binding results and then it quits working. I used ```var_dump()``` and nothing showed when I got that far. – jacdevelop Feb 09 '20 at 05:55
  • When I use the ```var_dump()``` after the ```$stmt->execute()```, this is what shows up: ```object(mysqli_stmt)#2 (10) { ["affected_rows"]=> int(-1) ["insert_id"]=> int(0) ["num_rows"]=> int(0) ["param_count"]=> int(1) ["field_count"]=> int(3) ["errno"]=> int(0) ["error"]=> string(0) "" ["error_list"]=> array(0) { } ["sqlstate"]=> string(5) "00000" ["id"]=> int(1) }```. I know that it is getting the username, because I tested that to make sure and it echo's it just fine. – jacdevelop Feb 09 '20 at 05:59
  • You don't show any code that binds results in the example above. I will remind you to check the values returned by mysqli functions. They return **false** if there was a problem. – Bill Karwin Feb 09 '20 at 08:24
  • Fixed to show the bind_result. Sorry about that. I'm not sure how to check the values. In MyPHP, I have a row with the username that I am trying to log in as. I registered it using a register page so that the password would be hashed and secure. It won't do anything one I add the bind_result coding. I tried echoing the ```$id, $user``` (but not the password) and nothing showed, just the cut off page again. – jacdevelop Feb 09 '20 at 17:13

1 Answers1

0

I tested your code, and it works. There is nothing wrong with it.

I suggest that despite you saying you double-checked the database, the problem is that the username doesn't exist in the database that this PHP code is connecting to. Maybe you checked the wrong database.

I tested your code as-is, then I refactored it a bit. I thought I'd show you the way I would write this:

This shows the use of error_log() which outputs to the http error file. It's a good habit to output the technical error message in a place where you can read it, but present a more user-friendly error in the browser output. You don't want to confuse your users.

$mysqli = new mysqli("localhost","USER","PASSWORD","DB");
if ($mysqli->connect_error) { 
    error_log($mysqli->connect_error);
    die('Error connecting to database, contact site administrator');
}   

Put the SQL in a variable, so you can output it to the error log if there's a problem. Again, the user doesn't need to know the technical details, they only need to know it failed and the site admin needs to fix it.

$sql = "
  SELECT admin_id, admin_username, admin_password 
  FROM admin 
  WHERE admin_username = ?";
if (($stmt = $mysqli->prepare($sql)) === false) {
  error_log($mysqli->error);
  error_log("SQL = [$sql]");
  die("Database error, contact site administrator");
}   

Every mysqli function returns false if there's a problem at any step. You need to check this.

if ($stmt->bind_param("s", $username) === false) {
  error_log($stmt->error);
  die("Database error, contact site administrator");
} 
if ($stmt->execute() === false) {
  error_log($stmt->error);
  die("Database error, contact site administrator");
} 
if ($stmt->store_result() === false) {
  error_log($stmt->error);
  die("Database error, contact site administrator");
}

If there are zero rows, it means the username didn't match anything. You want to know about this in the error log, but don't reveal it to the user. They should only know that either the username or password was wrong, not which one was wrong.

if ($stmt->num_rows == 0) {
  error_log("Username '$username' not found");
  die("Incorrect username or password");
} 
if ($stmt->bind_result($id, $user, $pass) === false) {
  error_log($stmt->error);
  die("Database error, contact site administrator");
} 

There should only be one row that matched the username. So if it doesn't have a matching password, feel free to die().

while ($stmt->fetch()) {
   if (password_verify($password, $pass) === false) {
       error_log("Username '$username' found, but password is wrong");
       die("Incorrect username or password");
   }
} 
$stmt->close();

Finally, last step: If we got this far, then it must be successful. If you die() at each error condition earlier, then you don't have to worry about deeply nested blocks of code.

echo "<p>Welcome! You are logged in, $username</p>";
Bill Karwin
  • 538,548
  • 86
  • 673
  • 828
  • I got as far as the ```store_result()``` and I got an error. The error log says: ```[10-Feb-2020 05:19:00 UTC] Commands out of sync; you can't run this command now [10-Feb-2020 05:19:05 UTC] PHP Notice: session_start(): A session had already been started - ignoring in /home/xk6wgsxybs5t/public_html/CookingForAlaska/includes/dblogin.php on line 7``` – jacdevelop Feb 10 '20 at 05:20
  • Aha - you must have run another SQL query already in this PHP request, and it's still in progress. See my answer to https://stackoverflow.com/a/3632320/20860 for an explanation of the "Commands out of sync" error. – Bill Karwin Feb 10 '20 at 07:48
  • Ok. So I changed the ```$sql``` to ```$sql2``` since I did see I have the other request and thought that would fix it. However, I still get an error ```[11-Feb-2020 22:30:06 UTC] Commands out of sync; you can't run this command now [11-Feb-2020 22:30:19 UTC] Commands out of sync; you can't run this command now```. I also tried removing the entire other SQL inquiry from the page entirely and still get an error of the same. I update my original post to show the entire coding from the page, including the other SQL inquiry. – jacdevelop Feb 11 '20 at 23:03
  • You're calling `store_result()` twice in a row. Is that causing the error? – Bill Karwin Feb 11 '20 at 23:44
  • I guess I'm not seeing where I call it twice unless the ```if``` statement is what is calling it again? – jacdevelop Feb 12 '20 at 01:44
  • Yes, when you call a function in an `if` expression, it does execute the function to get the result. – Bill Karwin Feb 12 '20 at 01:46