I am trying to build a simple user registration/login system, the registration form is functional enough for the time being, it works, but when I attempt to login using the username/password which are correct, my login.php script breaks when it runs the password_verify method. I am fairly new to web development, and have done a few days worth of googling / article reading before coming here. Here is the code
<?php
session_start();
if (isset($_POST['loginbtn'])) {
include 'dbh.php';
$uid = mysqli_real_escape_string($conn, $_POST['uid']);
$pwd = mysqli_real_escape_string($conn, $_POST['pwd']);
//Error handlers
//Check if inputs are empty
if (empty($uid) || empty($pwd)) {
header("Location: index.html?login=error");
exit();
} else {
$sql = "SELECT * FROM user WHERE uid='$uid'";
$result = mysqli_query($conn, $sql);
$resultCheck = mysqli_num_rows($result);
if ($resultCheck < 1) {
header("Location: index.html?login=error");
exit();
} else {
if ($row = mysqli_fetch_assoc($result)) {
//De-hashing the password
//something goes wronge here!!!!!!!!!
$hashedPwdCheck = password_verify($pwd, $row['pwd']);
if ($hashedPwdCheck == false) {
header("Location: index.html?login=error");
exit();
//BREAKPOINT!!!!
} elseif ($hashedPwdCheck == true) {
//Login the user here
$_SESSION['user_id'] = $row['user_id'];
$_SESSION['uid'] = $row['uid'];
$_SESSION['pwd'] = $row['pwd'];
header("Location: index.html?login=success");
exit();
}
}
}
}
$sql = "SELECT * FROM user WHERE uid='$uid' AND pwd='$pwd'";
$result = $conn->query($sql);
if (!$row = $result->fetch_assoc()) {
echo "username or password incorrect";
} else {
echo "login successful";
}
} else {
header("Location: index.html?login=error");
exit();
}
?>
also here is a screenshot of the user table on phpmyadmin
Any help would be greatly appreciated!
What exactly does āscript breaksā mean? Do you have error reporting turned on? What is the error message?
You need to use Prepared Statements. NEVER EVER put variables in a query
You need to check the Request Method not depend on the name of a button being submitted in order for the script to work.
How do you expect to use GET parameters on pages with a .html extension?
Do not SELECT *. Specify the column names you want
You do not need to explicitly check for true or false on the password check. The if statement already does that.
The last query is going to always fail.
Since you are just learning, I suggest you use PDO. Here is a tutorial to get you going. https://phpdelusions.net/pdo
1 Like
this may sound barbaric, but I basically changed the
header("Location: index.html?login=error");
to
header("Location: index.hl?login=error");
resulting in a āPage Not Foundā error wherever an error could occur in the login.php script, then tested each breakpoint until I isolated the error in the password_verify method. Again, fairly new to web development, Iām sure thereās a better way to do that, but Iām kinda learning as I go here.
1 Like
You can simplify checking for password by removing unnecessary code
if (password_verify($pwd, $row['pwd'])) {
//Login the user here
$_SESSION['user_id'] = $row['user_id'];
$_SESSION['uid'] = $row['uid'];
$_SESSION['pwd'] = $row['pwd'];
header("Location: index.html?login=success");
exit();
} else {
header("Location: index.html?login=error");
exit();
}
1 Like
The basics of debugging include verifying that your code has reached a certain point and that your variables contain the expected values. So try this:
//De-hashing the password
//something goes wrong here!!!!!!!!!
$pwdHashed = password_hash($pwd);
echo "Raw Password {$pwd}<br>";
echo "Hashed Password {$pwdHashed}<br>";
echo "Stored Password {$row['pwd']}<br>";
die('testing password');
And analyze the results.
I missed it earlier. DO NOT put the password in a session. Not now, not ever.
Is your pwd
column large enough to store the hashed password? I canāt see the length on the screen shot.
I know the discussion has been focusing on the password. But Iām interested in knowing what the difference is between user_id int(11)
and uid text
. It just doesnāt feel right to me somehow.
I believe text data types are larger than varchar so I donāt really think itās a matter of data types. But a matter of logic flaws.
SamA74
December 30, 2017, 7:04pm
10
elsheepo:
$sql = āSELECT * FROM user WHERE uid=ā$uidā AND pwd=ā$pwdāā;
$result = $conn->query($sql);
if (!$row = $result->fetch_assoc()) {
echo "username or password incorrect";
} else {
echo "login successful";
}
} else {
header(āLocation: index.html?login=errorā);
exit();
}
Whatās this last bit? Is it an older version that you forgot to delete?
Sorry for the delayed response all, I manged to dial this puppy in over the week. Here is the header.php it contains modal forms for both signup and login. Both working
<?php
session_start();
?>
<!DOCTYPE html>
<html lang="en">
<head>
<title>beatzz</title>
<link rel="icon" type="image/vnd.microsoft.icon" href="img/favicon.ico" />
<!-- metadata -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- Bootstrap core CSS -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<!-- jQuery JavaScript -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<!-- Bootstrap core JavaScript -->
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<!-- HTML5 shiv -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
<!-- Bootstrap overrides -->
<link rel="stylesheet" type="text/css" href="css/styles.css">
</head>
<body>
<div class="wrapper">
<!-- navbar -->
<nav class="navbar navbar-inverse navbar-fixed-top">
<div class="container-fluid">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#myNavbar" aria-expanded="false" aria-controls="navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar top-bar"></span>
<span class="icon-bar middle-bar"></span>
<span class="icon-bar bottom-bar"></span>
</button>
<img id="sheep" src="img/sheep.png">
</div>
<div class="collapse navbar-collapse" id="myNavbar">
<ul class="nav navbar-nav">
<li><a href="index.php">Updates</a></li>
<li><a href="projects.php">Projects</a></li>
<li><a href="docs.php">Documentation</a></li>
<li><a href="links.php">links</a></li>
<li><a href="contact.php">Contact</a></li>
</ul>
<ul class="nav navbar-nav navbar-right">
<?php
if (isset($_SESSION['user_uid'])) {
echo '<li><a href="includes/logout.inc.php"><span class="glyphicon glyphicon-log-in"></span> Logout</a></li>';
} else {
echo "<li><a onclick=\"document.getElementById('signup').style.display='block'\"><span class=\"glyphicon glyphicon-user\"></span>Signup</a></li>";
echo "<li><a onclick=\"document.getElementById('login').style.display='block'\"><span class=\"glyphicon glyphicon-log-in\"></span>Login</a></li>";
}
?>
</ul>
</div>
</div>
</nav>
<!-- The Login Modal -->
<div id="login" class="modal">
<span onclick="document.getElementById('login').style.display='none'"
class="close" title="Close Modal">×</span>
<form class="login-modal-content animate" action="includes/login.inc.php" method="POST">
<div class="imgcontainer">
<img id="blacksheep" src="img/blacksheep.png" alt="Avatar" class="avatar">
</div>
<div class="container">
<label><b>Username</b></label>
<input name="uid" class="form-control" id="uid" type="text" placeholder="Userame"
required data-validation-required-message="Please enter your username.">
<p class="help-block text-danger"></p>
<label><b>Password</b></label>
<input name="pwd" class="form-control" id="pwd" type="password" placeholder="Password"
required data-validation-required-message="Please enter your password.">
<p class="help-block text-danger"></p>
<button type="submit" name="loginbtn" class="loginbtn">Login</button>
<input type="checkbox" checked="checked"> Remember me
</div>
<div class="container">
<button type="button" onclick="document.getElementById('login').style.display='none'" class="cancelbtn">Cancel</button>
<span class="psw">Forgot <a href="#">password?</a></span>
</div>
</form>
</div>
<!-- The Signup Modal -->
<div id="signup" class="modal">
<span onclick="document.getElementById('signup').style.display='none'" class="signup-close" title="Close Modal">×</span>
<form class="signup-modal-content animate" action="includes/signup.inc.php">
<div class="imgcontainer">
<img id="blacksheep" src="img/blacksheep.png" alt="Avatar" class="avatar">
</div>
<div class="container">
<label><b>First Name</b></label>
<input name="first" class="form-control" id="first" type="text" placeholder="first name"
required data-validation-required-message="Please enter your first name.">
<p class="help-block text-danger"></p>
<label><b>Last Name</b></label>
<input name="last" class="form-control" id="last" type="text" placeholder="last name"
required data-validation-required-message="Please enter your last name.">
<p class="help-block text-danger"></p>
<label><b>Email Address</b></label>
<input name="email" class="form-control" id="email" type="text" placeholder="email@address.com"
required data-validation-required-message="Please enter your email address.">
<p class="help-block text-danger"></p>
<label><b>Username</b></label>
<input name="uid" class="form-control" id="uid" type="text" placeholder="username"
required data-validation-required-message="Please enter desired username.">
<p class="help-block text-danger"></p>
<label><b>Password</b></label>
<input name="pwd" class="form-control" id="pwd" type="password" placeholder="password"
required data-validation-required-message="Please enter your password.">
<p class="help-block text-danger"></p>
<label><b>Repeat Password</b></label>
<input name="pwd-repeat" class="form-control" id="pwd-repeat" type="password" placeholder="repeat password"
required data-validation-required-message="Please re-enter your password.">
<p class="help-block text-danger"></p>
<input type="checkbox" checked="checked"> Remember me
<p>By creating an account you agree to our <a href="privacy.php">Terms & Privacy</a>.</p>
<div class="clearfix">
<button type="button" onclick="document.getElementById('signup').style.display='none'" class="cancelbtn">Cancel</button>
<button type="submit" class="signupbtn">Sign Up</button>
</div>
</div>
</form>
</div>
<script>
// Get the modal
var login = document.getElementById('login');
var signup = document.getElementById('signup');
// When the user clicks anywhere outside of the modal, close it
window.onclick = function(event) {
if (event.target == login) {
modal.style.display = "none";
} elseif (event.target == signup) {
modal.style.display = "none";
}
}
</script>
And the signup.inc.php
<?php
if (isset($_POST['signupbtn'])) {
include_once 'dbh.inc.php';
$first = mysqli_real_escape_string($conn, $_POST['first']);
$last = mysqli_real_escape_string($conn, $_POST['last']);
$email = mysqli_real_escape_string($conn, $_POST['email']);
$uid = mysqli_real_escape_string($conn, $_POST['uid']);
$pwd = mysqli_real_escape_string($conn, $_POST['pwd']);
//Error handlers
//Check for empty fields
if (empty($first) || empty($last) || empty($email) || empty($uid) || empty($pwd)) {
header("Location: ../signup.php?signup=empty");
exit();
} else {
//Check if input characters are valid
if (!preg_match("/^[a-zA-Z]*$/", $first) || !preg_match("/^[a-zA-Z]*$/", $last)) {
header("Location: ../signup.php?signup=invalid");
exit();
} else {
//Check if email is valid
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
header("Location: ../signup.php?signup=email");
exit();
} else {
//Check if username is available
$sql = "SELECT * FROM users WHERE user_uid='$uid'";
$result = mysqli_query($conn, $sql);
$resultCheck = mysqli_num_rows($result);
if ($resultCheck > 0) {
header("Location: ../signup.php?signup=usertaken");
exit();
} else {
//Hashing the password
$hashedPwd = password_hash($pwd, PASSWORD_DEFAULT);
//Insert the user into database
$sql = "INSERT INTO users (user_first, user_last, user_email, user_uid, user_pwd) VALUES ('$first', '$last', '$email', '$uid', '$hashedPwd')";
mysqli_query($conn, $sql);
header("Location: ../index.php?signup=success");
exit();
}
}
}
}
} else {
header("Location: ../signup.php");
exit();
}
?>
and finally the login.inc.php
<?php
session_start();
if (isset($_POST['loginbtn'])) {
include_once 'dbh.inc.php';
$uid = mysqli_real_escape_string($conn, $_POST['uid']);
$pwd = mysqli_real_escape_string($conn, $_POST['pwd']);
//Error handlers
//Check if inputs are empty
if (empty($uid) || empty($pwd)) {
header("Location: ../index.php?login=error_empty");
exit();
} else {
//Check if username is in database
$sql = "SELECT * FROM users WHERE user_uid='$uid'";
$result = mysqli_query($conn, $sql);
$resultCheck = mysqli_num_rows($result);
if ($resultCheck < 1) {
header("Location: ../index.php?login=error_notfound");
exit();
} else {
//Check if password is correct
if ($row = mysqli_fetch_assoc($result)) {
//De-hashing the password
$hashedPwdCheck = password_verify($pwd, $row['user_pwd']);
if ($hashedPwdCheck == false) {
header("Location: ../index.php?login=error");
exit();
} elseif ($hashedPwdCheck == true) {
//Login the user here
$_SESSION['user_id'] = $row['user_id'];
$_SESSION['user_first'] = $row['user_first'];
$_SESSION['user_last'] = $row['user_last'];
$_SESSION['user_email'] = $row['user_email'];
$_SESSION['user_uid'] = $row['user_uid'];
header("Location: ../updates.php?login=success");
exit();
}
}
}
}
} else {
header("Location: ../index.php?login=error");
exit();
}
?>
Glad to see you got it working. Now switch to PDO and prepared statements you might have a usable solution. And maybe clean up some of the unnecessary if else combos.
2 Likes
Yeah, you need to put on your big boy pants and use PDO with Prepared Statements. The code may āworkā but it still has a handful of changes needed besides PDO.
1 Like
likeā¦ this!!!
dbh.inc.php
<?php
$servername = "localhost";
$username = "root";
$password = "********";
$database = "login";
try {
$conn = new PDO("mysql:host=$servername;dbname=$database", $username, $password);
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}
catch(PDOException $e) {
$conn = null;
echo "Connection failed: " . $e->getMessage();
}
?>
signup.inc.php
<?php
session_start();
// check whether the signupbtn was clicked
if (isset($_POST['signupbtn'])) {
include_once 'dbh.inc.php';
// initialize variable
$first = $_POST['first'];
$last = $_POST['last'];
$email = $_POST['email'];
$uid = $_POST['uid'];
$pwd = $_POST['pwd'];
$pwdRepeat = $_POST['pwd-repeat'];
// error handlers
// check for empty fields
if (empty($first) || empty($last) || empty($email) || empty($uid) || empty($pwd)) {
$conn = null;
header("Location: ../signup.php?signup=error_field");
exit();
} else {
// check if input characters are valid
if (!preg_match("/^[a-zA-Z]*$/", $first) || !preg_match("/^[a-zA-Z]*$/", $last)) {
$conn = null;
header("Location: ../signup.php?signup=error_name");
exit();
} else {
// check if email is valid
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
$conn = null;
header("Location: ../signup.php?signup=error_email");
exit();
} else {
// check if username is available
$stmt = $conn->prepare("SELECT * FROM users WHERE user_uid = ?");
$stmt->execute([$uid]);
if ($stmt->rowCount() > 0) {
$conn = null;
header("Location: ../signup.php?login=error_unavailable");
exit();
} else {
// check if the password was validated by the user
if (!pwdRepeat == pwd) {
$conn = null;
header("Location: ../signup.php?signup=error_passwords");
exit();
} else {
// hashing the password
$hashedPwd = password_hash($pwd, PASSWORD_DEFAULT);
// insert the user into database
$sql = "INSERT INTO users (user_first, user_last, user_email, user_uid, user_pwd) VALUES (?,?,?,?,?)";
$conn->prepare($sql)->execute([$first, $last, $email, $uid, $hashedPwd]);
// login the user in
$stmt = $conn->prepare("SELECT user_id, user_first, user_last, user_email, user_uid FROM users WHERE user_uid = ?");
$stmt->execute([$uid]);
$result = $stmt->fetchAll(PDO::FETCH_ASSOC);
$_SESSION['user_id'] = $result[0]['user_id'];
$_SESSION['user_first'] = $result[0]['user_first'];
$_SESSION['user_last'] = $result[0]['user_last'];
$_SESSION['user_email'] = $result[0]['user_email'];
$_SESSION['user_uid'] = $result[0]['user_uid'];
$conn = null;
header("Location: ../updates.php?login=success");
exit();
}
}
}
}
}
} else {
header("Location: ../signup.php?signup=error");
exit();
}
?>
login.inc.php
<?php
session_start();
// check whether the loginbtn was clicked
if (isset($_POST['loginbtn'])) {
include_once 'dbh.inc.php';
// initialize variable
$uid = $_POST['uid'];
$pwd = $_POST['pwd'];
// error handlers
// check if inputs are empty
if (empty($uid) || empty($pwd)) {
$conn = null;
header("Location: ../index.php?login=error_field");
exit();
} else {
// check if username is in database
$stmt = $conn->prepare("SELECT user_uid FROM users WHERE user_uid = ?");
$stmt->execute([$uid]);
if ($stmt->rowCount() < 1) {
$conn = null;
header("Location: ../index.php?login=error_username");
exit();
} else {
// check if password is correct
$stmt = $conn->prepare("SELECT user_pwd FROM users WHERE user_uid = ?");
$stmt->execute([$uid]);
$result = $stmt->fetchAll(PDO::FETCH_ASSOC);
// dehashing the password
$hashedPwdCheck = password_verify($pwd, $result[0]['user_pwd']);
if ($hashedPwdCheck == false) {
$conn = null;
header("Location: ../index.php?login=error_password");
exit();
} else {
// login the user in
$stmt = $conn->prepare("SELECT user_id, user_first, user_last, user_email, user_uid FROM users WHERE user_uid = ?");
$stmt->execute([$uid]);
$result = $stmt->fetchAll(PDO::FETCH_ASSOC);
$_SESSION['user_id'] = $result[0]['user_id'];
$_SESSION['user_first'] = $result[0]['user_first'];
$_SESSION['user_last'] = $result[0]['user_last'];
$_SESSION['user_email'] = $result[0]['user_email'];
$_SESSION['user_uid'] = $result[0]['user_uid'];
$conn = null;
header("Location: ../updates.php?login=success");
exit();
}
}
}
} else {
header("Location: ../index.php?login=error");
exit();
}
?>
Previously I have found that leading and trailing spaces often cause a problem and can be eliminated by using PHP trim(ā¦) where appropriate.
2 Likes
Good job on switching to PDO. There is still quite a bit to do to clean up the code though. Probably easier to just show you an example of what to do now. Study the code in my repository and see what you can learn from it. https://github.com/benanamen/perfect_app
system
Closed
April 10, 2018, 11:47pm
18
This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.