Jump to content

PHP Login System


Tom10

Recommended Posts

Hello, I am having issues with the login system that i am currently working on, it is showing login failed on the page when the login details for the user are correct.

 

Login.php

<?php

require('./includes/connect.php');

error_reporting(E_ALL | E_NOTICE);

if ($_SERVER['REQUEST_METHOD'] == "POST") {

	$username = $_POST['username'];
	$username = htmlentities($username);
	$password = $_POST['password'];
	$password = password_hash($password, PASSWORD_BCRYPT);

	$query = "SELECT username, password FROM apna_users WHERE username='$username' AND password='$password'";	
	$result = mysqli_query($mysqli, $query);
	$row = $result->fetch_array();

	if (password_verify($password, $row['password']) && $result->num_rows() > 0) {
		
		?>
		<html>
		<h2>Login Successful</h2>
		</html>
		<?php

	} else {
		?>
		<html>
		<h2>Login Failed</h2>
		</html>
		<?php
	}
}

?>

<html>

	<title>Apna Bhaiii - Login</title>

	<body>

	<center>

	<div id="login">

	<h1>Login to your account</h1><br>

	<form action="" method="POST">	
	<h3>Username:</h3>
	<input type="text" name="username" placeholder="Enter your username" /> <br>
	<h3>Password:</h3>
	<input type="password" name="password" placeholder="Enter your password" /> <br><br>
	<input type="submit" name="loginbtn" value="Log In" /> <br>
	</form>

	<h3>Don't have an account? <a href="register.php">Create one today</a></h3>

	</div>

	</center>

	</body>

</html>

Register.php (The register script works perfectly)

<?php

require('./includes/connect.php');

if($_SERVER['REQUEST_METHOD'] == "POST") {

	$email = $_POST['email'];
	$email= filter_var($email, FILTER_VALIDATE_EMAIL);
	$username = $_POST['username'];
	$username = htmlentities($username);
	$password = $_POST['password'];
	$cpassword = $_POST['cpassword'];


		if (!filter_var($email) || empty($username)) {
		echo "<b>Email address is invalid.</b>";
		}

		if (empty($username)) {
		echo PHP_EOL .  "<b>Username is empty</b>";
		}

		if (empty($password)) {
		echo PHP_EOL .  "<b>Password is empty or invalid</b>";
		}

		if($cpassword != $password) {
			die("The passwords do not match!");
		}
	
	$enc_password = password_hash($password, PASSWORD_BCRYPT);

	if (mysqli_query($mysqli, "INSERT INTO apna_users (email, username, password) VALUES ('$email', '$username', '$enc_password')")) {
		
		echo "Your account has been successfully created.";	
		echo '<meta http-equiv="refresh" content="1;login.php">';
		exit();

	} else {
		
		echo "An error has occured whilst creating your account, please try again later." . PHP_EOL . "If the problem persists please contact support.";

	}

}

?>
<html>

	<title>Apna Bhaiii - Register</title>

	<style>
	input {padding: 10px; border-radius: 20px; }
	#registerbtn1 input {width: 400px;}
	</style>

	<body>

	<center>

	<div id="register">

	<h1>Create your account</h1><br>

	<form action="" method="POST">
	<h3>E-mail Address:</h3>
	<input type="text" name="email" placeholder="Enter your E-Mail Address" required /> <br>
	<h3>Username:</h3>
	<input type="text" name="username" placeholder="Enter your username" required /> <br>
	<h3>Password:</h3>
	<input type="password" name="password" placeholder="Enter your password" required /> <br>
	<h3>Confirm Password:</h3>
	<input type="password" name="cpassword" placeholder="Confirm your password" required /> <br><br>
	<input type="submit" name="registerbtn" id="registerbtn1" value="Create" /> <br>
	</form>

	</div>

	</center>

	</body>

</html>

Does anyone know why it is doing this?,

 

Thanks :)

Link to comment
Share on other sites

Your code is wide open to SQL injection attacks, and you're misunderstanding password hashing.

 

Use prepared statements for dynamic query input. And fix the password check: password_hash() is only used to create a new hash during registration or a password reset. To verify a password, you fetch the user's hash and call password_verify() with the submitted password and the stored hash. You cannot do a database search with password_hash(), because the same password will always have a different hash due to the random salt.

Edited by Jacques1
  • Like 1
Link to comment
Share on other sites

<?php

require('./includes/connect.php');

error_reporting(E_ALL | E_NOTICE);

if ($_SERVER['REQUEST_METHOD'] == "POST") {

	$username = $_POST['username'];
	$username = htmlentities($username);
	$password = $_POST['password'];

	if ($query = $mysqli->prepare("SELECT username, password FROM apna_users WHERE username=? AND password=?")) {

		$query->bindParam("username", $username);
		$query->bindParam("password", $password);
		$query->execute();
		$query->bind_result($result);
		$result->fetch();

	}

	if (password_verify($password, $result['password']) && $result->num_rows() > 0) {
		
		?>
		<html>
		<h2>Login Successful</h2>
		</html>
		<?php
		$query->close();

	} else {
		?>
		<html>
		<h2>Login Failed</h2>
		</html>
		<?php
		$query->close();
	}
}

?>

<html>

	<title>Apna Bhaiii - Login</title>

	<body>

	<center>

	<div id="login">

	<h1>Login to your account</h1><br>

	<form action="" method="POST">	
	<h3>Username:</h3>
	<input type="text" name="username" placeholder="Enter your username" /> <br>
	<h3>Password:</h3>
	<input type="password" name="password" placeholder="Enter your password" /> <br><br>
	<input type="submit" name="loginbtn" value="Log In" /> <br>
	</form>

	<h3>Don't have an account? <a href="register.php">Create one today</a></h3>

	</div>

	</center>

	</body>

</html>

I have made those changes is this any better?, forgive me if i have mistakes in the code i am quite new to coding just trying to get my head around it

Link to comment
Share on other sites

The input password will not match that in the user table, so your selection criteria should just be where the username matches. Then verify the retrieved password hash.

I have changed that,

if ($query = $mysqli->prepare("SELECT username, password FROM apna_users WHERE username=?")) {

	$query->bindParam("username", $username);
	$query->execute();
	$result->fetch();

}
if (password_verify($password, $result['password']) && $result->num_rows() > 0) {
		
		?>
		<html>
		<h2>Login Successful</h2>
		</html>
		<?php

	} else {
		?>
		<html>
		<h2>Login Failed</h2>
		</html>
		<?php
	}

When i login, nothing is displayed it's just a blank page.

Link to comment
Share on other sites

Turn your error reporting on and all the way up.

 

Some mysqli methods you're calling don't even exist, and even those which do exist work completely different. It seems you're somehow trying to mix the mysqli library with the unrelated PDO extension, which of course makes no sense.

 

I gave you a link to the PHP manual which explains in great detail how prepared statements in mysqli work. Read it. Programming is an exact science, so you need to use the actual mysqli API rather than what you think the API should look like.

 

By the way, mysqli sucks compared to PDO, so if there's a chance to switch, I recommend you do that. Clearly you already prefer PDO.

Edited by Jacques1
  • Like 1
Link to comment
Share on other sites

I have turned on error reporting and switched to PDO, However i still recieve a blank page when logging in

<?php

require('./includes/connect.php');

error_reporting(E_ALL);

if ($_SERVER['REQUEST_METHOD'] == "POST") {

	$username = $_POST['username'];
	$username = htmlentities($username);
	$password = $_POST['password'];

	$query = $mysqli->prepare("SELECT username FROM apna_users WHERE username=?");
	$query->bindParam('?', $username, PDO::PARAM_STR, 50);
	$query->execute();
	$row = $query->fetch(PDO::FETCH_ASSOC);

	if (password_verify($password, $row['password']) && $query->num_rows() > 0) {

		echo "Login Successful";

	} else {

		echo "Login Failed.";

	}
}

?>

<html>

	<title>Apna Bhaiii - Login</title>

	<body>

	<center>

	<div id="login">

	<h1>Login to your account</h1><br>

	<form action="" method="POST">	
	<h3>Username:</h3>
	<input type="text" name="username" placeholder="Enter your username" /> <br>
	<h3>Password:</h3>
	<input type="password" name="password" placeholder="Enter your password" /> <br><br>
	<input type="submit" name="loginbtn" value="Log In" /> <br>
	</form>

	<h3>Don't have an account? <a href="register.php">Create one today</a></h3>

	</div>

	</center>

	</body>

</html>
Link to comment
Share on other sites

to cause all php detected errors to be reported and displayed, you need to set php's error_reporting to E_ALL (it should always be set to this) and set display_errors to ON. these should be set in the php.ini on your development system, so that ALL php errors will be reported (setting them in your code won't help with php syntax errors) and so that you don't need to remember to set them to get php to help you or forget to remove them form your code when you put it onto a live server (you should log all php errors on a live server, not display them to the visitor.)

 

you still have some problems in the posted code -

 

1) htmlentities() is an OUTPUT function. it is used when you output data to the browser. it is not used on input data and it has nothing to do with data used with an sql query.

 

2) $mysqli. if you have switched to using the PDO extension, name the variable holding the instance of the PDO class something helpful like $pdo.

 

3) the first parameter in your bindParam() statement isn't correct. it's either the place-holder number (starting at 1), when using ? place-holders, or its the named place-holder. basic information like this can always be found in the php.net documentation.

 

4) your sql query is only SELECT'ing the username. therefor, $row['password'] won't exist. this would be throwing an undefined index error once you have php's error_reporting/display_errors set as suggested.

 

5) you also need to fetch the row and test if the query matched a row, all at the same time. the current code will throw php errors at the $row['password'] if the query doesn't match any row. you can do this - 

if($row = $query->fetch(PDO::FETCH_ASSOC))
{
    // the query matched a row, use password_verify() here...
}
Edited by mac_gyver
Link to comment
Share on other sites

First off, make sure you have the PDO connection parameters right. For example, there's no manual error handling in your code, which means you must make PDO throw an exception in case of an error (otherwise you'd just keep going).

 

A good starting point is this:

<?php

const DB_HOST = 'localhost';
const DB_USER = '...';
const DB_PASSWORD = '...';
const DB_NAME = '...';
const DB_CHARSET = 'UTF8';



$dsn = 'mysql:host='.DB_HOST.';dbname='.DB_NAME.';charset='.DB_CHARSET;
$databaseConnection = new PDO($dsn, DB_USER, DB_PASSWORD, [
    PDO::ATTR_EMULATE_PREPARES => false,                // use actual prepared statements, don't emulate them
    PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,        // make PDO throw an exception in case of an error
    PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,   // fetch associative arrays by default
]);

The password check itself can be simplified to

$userStmt = $databaseConnection->prepare('
    SELECT
        user_id,  -- I am guessing here
        password  -- password_hash would be a better name
        -- add additional columns if needed
    FROM
        apna_users
    WHERE
        username = :username    -- use named parameters for the sake of readability
');
$userStmt->execute([
    'username' => $username,
]);
$user = $userStmt->fetch();

if ($user && password_verify($password, $user['password']))
{
    echo 'Credentials correct.';
}
else
{
    echo 'Username or password incorrect.';
}
  • Like 1
Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.