Im struggling to convert my login system to prepared statements. I have managed to convert my entire Crud system but just confused with this last part. Any help would be much appreciated.
This was the original login without prepared statements:
if(isset($_POST['submit'])) {
$user = mysqli_real_escape_string($con, $_POST['username']);
$password = mysqli_real_escape_string($con, $_POST['password']);
if($user == "" || $password == "") {
echo "Either username or password field is empty.";
echo "<br/>";
echo "<a href='login.php'>Go back</a>";
} else {
$result = mysqli_query($con, "SELECT * FROM login WHERE username='$user' AND password=md5('$password')")
or die("Could not execute the select query.");
$row = mysqli_fetch_assoc($result);
if(is_array($row) && !empty($row)) {
$validuser = $row['username'];
$_SESSION['valid'] = $validuser;
$_SESSION['name'] = $row['name'];
$_SESSION['id'] = $row['id'];
} else {
echo "Invalid username or password.";
echo "<br/>";
echo "<a href='login.php'>Go back</a>";
}
if(isset($_SESSION['valid'])) {
header('Location: index.php');
}
}
} else {
?>
<div class="row">
<div class="col-md-6 col-md-offset-3">
<div class="box">
<h3>Login</h3>
<form name="form1" action="" method="POST" enctype="multipart/form-data">
<input type="text" name="username" id="username" placeholder="Username" class="form-control"><br>
<input type="password" name="password" id="password" placeholder="Password" class="form-control"><br>
<button type="submit" name="submit" class="btn btn-success button">Login</button>
</form>
</div>
</div>
<?php
}
?>
</body>
</html>
And then my index.php page
<?php
if(isset($_SESSION['valid'])) {
include("connect.php");
$result = mysqli_query($con, "SELECT * FROM login");
?>
Welcome <?php echo $_SESSION['name'] ?> ! <a href='logout.php'>Logout</a><br/>
<br/>
<a href='view.php'><?php echo ("<div class='alert alert-success'>Click here to View and Add Products!</div>")?></a>
<a href='viewuser.php'><?php echo ("<div class='alert alert-success'>Click here to Add Users!</div>")?></a>
<br/><br/>
<?php
} else {
echo ("<div class='alert alert-danger'>You must be logged in to access CMS site.</div>");
echo "<a href='login.php' class='btn btn-primary'>Login</a>";
}
?>
This is what I have done so far:
if(isset($_POST['submit'])) {
$user = $_POST['username'];
$password = md5(['password']);
$sql = $con->prepare("SELECT * FROM login WHERE username = ? AND password = ?");
$sql->bind_param("ss", $user, $password);
$sql->execute();
$result = $sql->get_result();
while($row = $result->fetch_assoc()) {
$row = mysqli_fetch_assoc($result);
if(is_array($row) && !empty($row)) {
$validuser = $row['username'];
$_SESSION['valid'] = $validuser;
$_SESSION['name'] = $row['name'];
$_SESSION['id'] = $row['id'];
} else {
echo "Invalid username or password.";
echo "<br/>";
echo "<a href='login.php'>Go back</a>";
}
if(isset($_SESSION['valid'])) {
header('Location: index.php');
}
}
}
?>
<div class="row">
<div class="col-md-6 col-md-offset-3">
<div class="box">
<h3>Login</h3>
<form name="form1" action="" method="POST" enctype="multipart/form-data">
<input type="text" name="username" id="username" placeholder="Username" class="form-control"><br>
<input type="password" name="password" id="password" placeholder="Password" class="form-control"><br>
<button type="submit" name="submit" class="btn btn-success button">Login</button>
</form>
</div>
</div>
</body>
</html>
Its on this part that I am getting so confused as to how to implement it in prepared statements with the index.php No matter what I try from searching the internet, I just cant seems to get this part figured out:
$row = mysqli_fetch_assoc($result);
if(is_array($row) && !empty($row)) {
$validuser = $row['username'];
$_SESSION['valid'] = $validuser;
$_SESSION['name'] = $row['name'];
$_SESSION['id'] = $row['id'];
} else {
echo "Invalid username or password.";
echo "<br/>";
echo "<a href='login.php'>Go back</a>";
}
if(isset($_SESSION['valid'])) {
header('Location: index.php');
}
}
}
As the comments already point out, one should use an appropriate function like password_hash(), and store the hashes in a field of type varchar(255)
:
// Hash a new password for storing in the database.
// The function automatically generates a cryptographically safe salt.
$hashToStoreInDb = password_hash($password, PASSWORD_DEFAULT);
In the login form, we cannot verify the password directly with SQL, nor can we search for it, because the stored hashes are salted and the calculation of a single hash takes a lot of time. Instead we...
Below you can find a code example for mysqli, showing how to do the password verification with a mysqli connection. The code has no error checking to make it readable:
/**
* mysqli example for a login with a stored password-hash
*/
$mysqli = new mysqli($dbHost, $dbUser, $dbPassword, $dbName);
$mysqli->set_charset('utf8');
// Find the stored password hash in the db, searching by username or email
$sql = 'SELECT password FROM users WHERE username = ?';
$stmt = $mysqli->prepare($sql);
$stmt->bind_param('s', $_POST['username']); // it is safe to pass the user input unescaped
$stmt->execute();
// If this user exists, fetch the password-hash and check it
$isPasswordCorrect = false;
$stmt->bind_result($hashFromDb);
if ($stmt->fetch() === true)
{
// Check whether the entered password matches the stored hash.
// The salt and the cost factor will be extracted from $hashFromDb.
$isPasswordCorrect = password_verify($_POST['password'], $hashFromDb);
}