I am in the process of creating a signup system using mysql and PHP. I have been able to connect the system to a database and it works for when the username and password entered are correct. However, when the username and password is not correct (i.e anytime when the username/password pair is not stored in the database), it just leads to a blank white page. Currently, my code has it so that when the username and password are not correct, it prints our "Invalid username of password". Please see the code below, any help is appreciated. Thank you in advance!
<?php
require_once 'source/session.php';
require_once 'source/db_connect.php';
if(isset($_POST['login-btn'])) {
$user = $_POST['user-name'];
$password = $_POST['user-pass'];
try {
$SQLQuery = "SELECT * FROM users WHERE username = :username";
$statement = $conn->prepare($SQLQuery);
$statement->execute(array(':username' => $user));
while($row = $statement->fetch()) {
$id = $row['id'];
$hashed_password = $row['password'];
$username = $row['username'];
if(password_verify($password, $hashed_password)) {
$_SESSION['id'] = $id;
$_SESSION['username'] = $username;
header('location: dashboard.php');
}
else {
echo "Error: Invalid username or password";
}
}
}
catch (PDOException $e) {
echo "Error: " . $e->getMessage();
}
}
?>
Well, currently your SQL query would return a set with 0 rows for a non-existent user, but that would not cause an error. It would just be an empty result set. Therefore it would not go through the while loop, it would just terminate without an error.
Your logic is leaving out the check to see whether $statement->rowCount() is zero.
To clarify in case this answer is confusing: You have 0 results if you enter a username that doesn't exist... then you do while(0) so you never get into that part of the code. No password check is done. And no error is thrown, so you never escape the try{} and get into the catch{} portion of the code. There is nothing returned here if the username turns up zero results from the database. You need to add another error in that case.
Related
I'm trying to has a password in PHP using password_hash and password_verify. I am correctly hashing the password as it is being into the database hashed, but when I attempt to unhash the password whilst logging in, it doesn't seem to want to work. The password is being recieved from an Android application but after echoing both the username and the password, they are correct to what they should be. To hash the password, I am using PASSWORD_DEFAULT as the hashing technique.
Code:
<?php
error_reporting(0);
require_once('dbconnect.php');
$username = $_POST["username"];
$password = $_POST["password"];
$result = $conn->query("SELECT * FROM User WHERE username ='$username'");
if(empty($result)){
die("Username doesn't exist");
}
$dbpass = $conn->query("SELECT password FROM User WHERE username = '$username'");
if (password_verify($password, $dbpass)){
$stmt = "SELECT * FROM User WHERE username='$username' and password='$password'";
$check = mysqli_fetch_array(mysqli_query($conn, $stmt));
if(isset($check)){
echo "success";
}else{
echo "Invalid Username or Password";
}
}
else {
echo "password not unhashing";
}
$conn->close();
Am I missing something obvious?
First, use prepared statements to remove the threat of SQL injection, or your login screen becomes an attack vector. Then the problem is you're not getting the actual dbpass, you're getting a result set containing $dbpass, without dereferencing it.
Try it this way:
//username in where clause is coming from the user, don't execute it
//also fetch a clean copy of the username from the database we can trust to do things with like display -- assuming we filtered it on the way into the database.
$stmnt = $conn->prepare('select username,password from user where username = ?') or die('...');
//username must be a string, and to keep it clear it came from a user, and we don't trust it, leave it in POST.
$stmnt->bind_param('s',$_POST['username']) or die('...');
//Do the query.
$stmnt->execute() or die('...');
//Where to put the results.
$stmnt->bind_result($username,$dbpass);
//Fetch the results
if($stmnt->fetch()) //get the result of the query.
{
if(password_verify($_POST['password'],$dbpass))
{
//The password matches.
}
else
{
//password doesn't match.
}
}
else
{
//username is wrong.
}
I'm just new in PHP, I have the project which I'm still constructing and now Am working on
Administrator area.
For now I'm writing the script which Update the password in the table by looking two criteria
"username and fname" if the same with the entered one the password should change, And It does so successfully, but the problem is once I enter incorrect username it still update the password and doesn't show the message "The username you entered does not exist" as well as when I write wrong fname it doesn't show the message to, It real make me stacking where Am wrong, although I know there some where A'm wrong.
I request for any help to any one I'w be thankfully.
This my script
<?php
session_start();
//include mysqli_connect
$name = $_POST['fname'];
$newp = $_POST['newpword'];
$user=$_POST['username'];
$result = mysql_query("SELECT password FROM admin WHERE fname='$name'
AND username='$user' ");
if(!$result)
{
echo "The username you entered does not exist";
}
elseif(mysql_num_rows($result)>0)
$result=mysql_query("UPDATE admin SET password='$newp' where fname='$name'");
{
echo "Password change successfully";
echo"<br>";
echo"<a href=index.php> Click here to signin </a>";
exit;
}
{
echo "The new password and confirm new password fields must be the same";
}
?>
Your if statement and brackets are very mixed up in the code. I think I understood what you're trying to do, though... but you should really go through your own code and give everything the correct indentation.
I changed your code to use pdo.
I added a POST value for the old user password because you should really verify that, too, when updating a user password even if they are already logged in. You will need to add a field for that in the form this is being sent from. If you don't want to use it, you will just need to take the logic out of the code.
And - I really hope you aren't storing the password in plain text. If you are, please tell me what your exact PHP version is in a comment below this post and I can update my answer to show how you would go about storing and using hashed passwords. It does really depend on the version, though.
<?php
session_start();
$_POST['fname'] = 'fname';
$_POST['newpword'] = 'newpword';
$_POST['username'] = 'username';
$name = (isset($_POST['fname'])) ? $_POST['fname'] : die("\$_POST['fname'] is not set");
$newp = (isset($_POST['newpword'])) ? $_POST['newpword'] : die("\$_POST['newpword'] is not set");
$user = (isset($_POST['username'])) ? $_POST['username'] : die("\$_POST['username'] is not set");
// you should get the old password, too,
// so you can verify that it's the correct user
$_POST['oldpass'] = 'password';
$oldp = (isset($_POST['oldpass'])) ? $_POST['oldpass'] : die("\$_POST['oldpass'] is not set");
$pdo = new PDO("mysql:host=localhost;dbname=test", 'root', 'password');
$stmt = $pdo->prepare("SELECT password FROM admin WHERE fname=:fname AND username=:user");
$stmt->bindParam(':fname', $name);
$stmt->bindParam(':user', $user);
$success = $stmt->execute();
$result = $stmt->fetch(PDO::FETCH_ASSOC);
if ($success===false) {
print "an error occurred in the query <br/>".print_r($stmt->errorInfo(),true);
}
elseif ($success!==false && $result===false)
{
print "that username was not found in the database";
}
else
{
if ($result['password']==$oldp)
{
$stmt2 = $pdo->prepare("UPDATE admin SET password=:newp where fname=:fname");
/* You should really HASH this password before storing it*/
$stmt2->bindParam(':newp', $newp);
$stmt2->bindParam(':fname', $name);
$success2 = $stmt2->execute();
if ($success2!==false)
{
echo "Password change successfully";
echo"<br>";
echo"<a href=index.php> Click here to signin </a>";
}
else
{
print "an error occurred updating the password <br/>";
}
}
else
{
print "old password didn't match";
}
}
?>
I think the problem is with if($result) condition. Instead of checking $result you should check if(mysql_num_rows($result)>0)
Okay.. I am completely new to this PDO stuff.. I have tried to recreate my mysql script (working) to a PDO script (not working).. I have tested that my DB login informations is correctly programmed for PDO..
This is my PDO script...
<?
session_start();
//connect to DB
require_once("connect.php");
//get the posted values
$email=htmlspecialchars($_POST['email'],ENT_QUOTES);
$pass=md5($_POST['psw']);
//now validating the email and password
$sql - $conn_business->prepare( "SELECT email, password FROM members WHERE email='".$email."'");
$sql -> execute();
$count = $sql->rowCount();
$result = $sql -> fetch();
// Now use $result['rowname'];
$stmt = $conn_business->prepare("SELECT * FROM members WHERE email='".$email."'");
$stmt ->execute();
$act = $stmt -> fetch();
//if email exists
if($count > 0)
{
//compare the password
if(strcmp($result["password"],$pass)==0)
{
// check if activated
if($act["activated"] == "0")
{
echo "act"; //account is not activated yet
}
else
{
echo "yes"; //Logging in
//now set the session from here if needed
$_SESSION['email'] = $email;
}
}
else
echo "no"; //Passwords don't match
}
else
echo "no"; //Invalid Login
?>
And this is my old mysql script...
session_start();
require_once("connect.php");
//get the posted values
$email=htmlspecialchars($_POST['email'],ENT_QUOTES);
$pass=md5($_POST['psw']);
//now validating the username and password
$sql="SELECT email, password members WHERE email='".$email."'";
$result=mysql_query($sql);
$row=mysql_fetch_array($result);
$sql2="SELECT * FROM members WHERE email='".$email."'";
$result2=mysql_query($sql2);
$row2=mysql_fetch_array($result2);
$act = $row2['activated'];
//if username exists
if(mysql_num_rows($result)>0)
{
//compare the password
if(strcmp($row['password'],$pass)==0)
{
// check if activated
if($act == "0")
{
echo "act";
}
else
{
echo "yes";
//now set the session from here if needed
$_SESSION['email'] = $email;
}
}
else
echo "no";
}
else
echo "no"; //Invalid Login
Does anybody know, what I have done wrong? It is an automatically script.. It is called through AJAX and return data based on 'no', 'yes' and 'act' that tells the AJAX/jQuery script what to do.. As I said - the mysql script is working, so please if anyone could tell me what I have done wrong with the PDO script..
EDIT:
when it returns the data to the jQuery script, this should happen:
if yes: start session, redirect to page2.php with session started.
else if act: write in a field that the account is not activated.
else: write that email and password didn't match.
The thing is, that when I try to write the correct e-mail and password - it continues to write : "email and password didn't match" instead of redirecting.. When I say that it is not working it is because the mysql script does as described but the PDO script doesn't..
And I have tried to change the 'echo "no";' to 'echo "yes";' to see if the login would start anyway, but somehow it continues to write that the email and password didn't match..
SOLUTION:
I ahven't told this because I thought it was unnecessary, but the reason for it not to work was because of that i have had my old mysql code in comment marks on top of the page, so that the session_start command didn't work.. After deleting the old code it worked, but then I found something else to change, and that is in the PDO script when it is validating it says:
$sql - $conn_business->prepare( "SELECT email, password FROM members WHERE email='".$email."'");
and then I just changed the '-' after $sql to '=' and now, everything works perfectly... Anyhow thank you everybody.. hope this code can help others..
Did you even read the manual before you "started using" PDO?
That is not how prepared statements are supposed to be used! Your code is filled with SQL injections.
Why are you selecting same row twice ?
The strcmp() is not for checing if one string is identical to another.
And hashing passwords as simple MD5 is just a sick joke.
session_start();
//very stupid way to acquire connection
require_once("connect.php");
//get the posted values
$email = htmlspecialchars($_POST['email'],ENT_QUOTES);
if (filter_var( $email, FILTER_VALIDATE_EMAIL))
{
// posted value is not an email
}
// MD5 is not even remotely secure
$pass = md5($_POST['psw']);
$sql = 'SELECT email, password, activated FROM members WHERE email = :email';
$statement = $conn_business->prepare($sql);
$statement->bindParam(':email', $email, PDO::PARAM_STR);
$output = 'login error';
if ($statement->execute() && $row = $statement->fetch())
{
if ( $row['password'] === $pass )
{
// use account confirmed
if ( $row['activated'] !== 0 ) {
$output = 'not activated';
$_SESSION['email'] = $email;
}
$output = 'logged in';
}
}
echo $output;
i believe the second query in your scripts is not necessary you could simple do
SELECT * FROM members WHERE email=:EMAIL AND password=:PWS;
use bindParam method
$qCredentials->bindParam(":EMAIL",$EMAIL);
$qCredentials->bindParam(":PWS",$PWS);
then do more understable outputs rather than yes or no..
try "Unable to login: Invalid credentials supplied" for invalid types of values or "Unable to login: Invalid credentials, couldn't find user" for invalid user credentials.
You could try to start the session after the user has been successfully logged in your IF condition returning yes, and the methods
$PDOstatement->debugDumpParams()
$PDOstatement->errorInfo()
$PDOstatement->errorCode()
will help you understand what went wrong with a query!
I want to check which one of the username or password is incorrect in a single mysql query.
Scenario:
When a user types a username and password and clicks submit, I want to show an error message which one is incorrect. I need a simple and optimized query for this.
As a general rule of thumb I would say it's better return a message back to the user saying that "The username or password is incorrect" as it wouldn't indicate to an attacker if the username or password was wrong.
That's a nice way for an attacker to find valid usernames.
To answer your question, I think you'd have to do
SELECT username, password WHERE username=? OR password=?
and then go through the results with the given username and password, to find the right one.
$query = <<<EOL
SELECT IF(password = '$password', 1, 0)
FROM users
WHERE username='$username'
EOL;
$result = mysql_query($query)
if (mysql_numrows($result) == 0) then
echo 'Bad username';
} else {
$row = mysql_fetch_array($result);
if ($row[0] == 0) then
echo 'Bad password';
}
}
Of course, this assumes $username and $password have been properly escaped, and that $password has been massaged into whatever hash/encryption method you're using to store it in the DB.
Please use HTMl form with POST method the use following code::
<?php
$con = mysql_connect("localhost","username","password");
if (!$con)
{
die('Could not connect: ' . mysql_error());
}
mysql_select_db("My_TABLE_NAME", $con);
$Username = $_POST['Username']; // get username
$Password = $_POST['Password'] ; // get pwd
$sql="SELECT Username FROM My_TABLE_NAME WHERE Username=’".$Username.”’ and Password=’”.$Password.”’”;
$r = mysql_query($sql);
if(!$r) {
$err=mysql_error();
print $err;
exit();
}
if(mysql_affected_rows()==0){
print "no such login in the system. please try again.";
exit();
}
else{
print "successfully logged into system.";
//proceed to perform website’s functionality – e.g. present information to the user
}
?>
Hey This is my login script, using PHP5 and MYSQLi, I just had help spotting errors in my query, but still it will not let me login, even though the username and password are correct and in the database, it just keeps returning the error: your username and password do not match any in our db. But I know they do lol...could any body spot the problem?
//Check if the form has been submitted
if (isset($_POST['login']))
{
//Check if username and password are empty
if ($_POST['username']!='' && $_POST['password']!='')
{
//Create query to check username and password to database
$validate_user = $mysqli->query('SELECT id, username, password, active FROM users WHERE = username = "'.$mysqli->real_escape_string($_POST['username']).'" AND password = "'.$mysqli->real_escape_string(md5($_POST['password'])).'"');
//We check if the query returns true
if ($validate_user->num_rows == 1)
{
$row = $validate_user->fetch_assoc();
//Check if the user has activated there account
if ($row['activated'] == 1)
{
$_SESSION['id'] = $row['id'];
$_SESSION['logged_in'] = true;
Header('Location: ../main/index.php');
}
//Show this error if activation returns as 0
else {
$error = '<p class="error">Please activate your account.</p>';
}
}
//Show this error if the details matched any in the db
else {
$error = '<p class="error">Your username and password are not in our database!</p>';
}
}
//Show this error if the username and password field have not been entered
else {
$error = '<p class="error">Please enter your username and password.</p>';
}
}
Instead of
SELECT ... FROM users WHERE = username = ...
It should be
SELECT ... FROM users WHERE username = ...
If you keep getting problems like this, try storing the query in a variable and echo it, so you can copy-paste it into your database management tool and see if there are any query errors.
To make it most reliable way, I'd suggest to trigger this error according to main error handling settings:
//just in sake of readability
$user = $mysqli->real_escape_string($_POST['username']);
$pass = $mysqli->real_escape_string(md5($_POST['password']));
$sql = "SELECT id, username, password, active FROM users
WHERE username = '$user' AND password = '$pass'";
$res = $mysqli->query($sql) or trigger_error(mysqli->error.$sql);
note that trigger_error function. it will bring error message to the standard error output. On the development PC it will be browser's screen or a log file on the production server.