I have been going through the password_hash() and password_verify() methods in PHP and I've been trying to include that in my code. I can't seem to get it to work, I've gone through series of googling and even some of the questions here on SO but they don't seem to resolve the issue.
My column length in the database is 255. When I try to run the code, I get the $loginerror message. Here's my code block. Please what am I doing wrong.
$signin_email=$_POST['signin_email'];
$signin_password=$_POST['signin_password'];
if($valid){
require_once 'scripts/connect_to_mysql.php';
$sql = "SELECT First_name, Last_name,Password FROM customer WHERE Email=? AND Password=? LIMIT 1";
$stmt=$conn->prepare($sql);//preparing the statement
if(!$stmt){
echo "Unable to prepare: ".$conn->errno. " " .$conn->error;
}
//executing the statement
//$date=date('d m Y h:i:s');
if(!$stmt->bind_param('ss', $signin_email, $signin_password)){//bind parameters to sql statement. i=integer, s=string, b=blob, d=double
echo "Binding parameters failed: ".$stmt->errno. " " . $stmt->error;
}
if(!$stmt->execute()){//executing the statement
echo "Statement Execution failed: ". $stmt->error;
}
if(!$stmt->bind_result($dbfirstname,$dblastname,$dbpassword)){// used to bind variables to a prepared statement for result storage
echo "Unable to bind results to variables: ".$stmt->error;
}
$stmt->store_result();
//echo $stmt->num_rows;
echo $dbpassword;
if(password_verify($signin_password, $dbpassword)){
if($stmt->num_rows===1){//to check if username and password actually exists
while($row=$stmt->fetch()){
$user=$dbfirstname. " ". $dblastname;
echo $user;
}
/*$_SESSION['user']=$user;
header('location:logintest.php');
exit();*/
}
}
else{
//$error="Invalid Email address/Password. Please try again";
$loginerror= "Invalid Email address/Password. Please try again";
}
$stmt->close();//closing the prepared statement
$conn->close();//closing the connection
}
Problem does not lie in password_verify but in way that you build your query:
`$sql ="SELECT First_name, Last_name,Password FROM customer WHERE Email=? AND Password=? LIMIT 1";
You bind $signin_password to that query and it contains not hashed value from $_POST.
There are 2 solutions:
1) remove AND Password=? from your query - you will check your password with password_verify
2) change $signin_password to:
$signin_password=password_hash($_POST['signin_password']);
(but this way using password_verify is kind of irrelevant.
$signin_password=$_POST['signin_password'];
$hash = password_hash($dbpassword, PASSWORD_DEFAULT);
if (password_verify($signin_password, $hash))
{
echo 'Password is valid!';
}
else
{
echo 'Invalid password.';
}
Try with this :) Better option is just build your own query.
Related
I have a file register.php for my site.
$username=filter_var($_POST['username'], FILTER_SANITIZE_STRING);
$sql="SELECT username FROM users WHERE username=?";
$stmt=$con->prepare($sql);
$stmt->bind_param('s', $username);
$stmt->execute();
$result = $stmt->get_result();
$stmt->close();
while ($row = $result->fetch_object()) {
if(empty($row->username)) {
echo "different username. IS OK !!";
} else {
echo "<font color='red'>*</font>".$username."<font color='red'> : this username already exist in DB!!</font><br />";
}
}
Here I compare the ($username from form) with ($row->username from DB)
$row->username exist only if $username is already register. So, if this exist, will go on ELSE part.
If $row->username doesn't exist (is empty) , because SELECT from sql will find no attribute, my code must go on IF part and display this message "different username. IS OK !!"
Why IF part doesn't work? I know sql will return 0, or NULL or "" or something like this. If I put a username which is not already registered, the code don't show the specific message. Because in this part I want to change the message with the code which permit to register new username.
empty($row->username) is not really empty if SQL can't find something to return?
Another problem is : I have a registered username "Test". MySQL is not case-sensitive, but in php, I can register another username "test". The code in php will run as a new register, but in MySQL nothing will happening because "username is unique" there. So, in "check username" from above, I need to check 2 insensitive variables ($username and $row->username). Because if in DB I have Test, and I want to register new user "test", this code will let me to do it. I want to show a error message if this happening.
All you need is to verify if no rows are returned.
$username=filter_var($_POST['username'], FILTER_SANITIZE_STRING);
$sql="SELECT username FROM users WHERE username=?";
$stmt=$con->prepare($sql);
$stmt->bind_param('s', $username);
$stmt->execute();
$count = $stmt->num_rows;
if ($count == 0) {
// Username not in table
} else {
// Username already exists
]
To be sure that all your usernames are lowercase, simply convert it to lowercase before inserting it.
$username = strtolower($username);
i think you should covert your database and php variable into same case then compare it for checking.
$username=filter_var($_POST['username'], FILTER_SANITIZE_STRING);
$sql="SELECT LCASE(username) AS username FROM users WHERE username=?";
$stmt=$con->prepare($sql);
$stmt->bind_param('s', strtolower($username)); // used strtolower();
$stmt->execute();
Try this code, hope this helps...
thanks for fast answers. Honestlly, I don't know where was the issue, because now it's run perfect, without strtolower method. This is my code now:
$sql="SELECT username FROM users WHERE username=?";
$stmt=$con->prepare($sql);
$stmt->bind_param('s', $username);
$stmt->execute();
$result = $stmt->get_result();
$row = $result->fetch_object();
$stmt->close();
if(empty($row->username)) {
// if a cell from below is empty, go on ELSE part
if (!empty($username) && !empty($password) && !empty($email) && !empty($country)) {
$sql="INSERT INTO users (username, password, email, borned, gender, country, phone, register_date) VALUES (?,?,?,?,?,?,?, now())";
$stmt = $con->prepare($sql);
$stmt->bind_param('sssssss', $username, $password, $email, $borned, $gender, $country, $phone);
$stmt->execute();
$stmt->close();
header ("Location: login.php");
} else {
echo "<font color='red'>*Must complete required cells !!</font> ";
}
// end of register dates
} else {
echo "<font color='red'>*</font>".$username."<font color='red'> : this username already exist in DB!!</font><br />";
}
I have user "Test", if try to register "test" will give a message that the user is already registered.
Thanks again, the thread can be deleted is somebody consider that can not help somebody :D
I am using prepared statements to log in, but I am not able to log in with any password and username pairs. I don't know why. It seems like $result = $stmt->get_result(); never returns false because when I print $result, I get:
result: mysqli_result Object (
[current_field] => 0 [field_count] => 2 [lengths] => [num_rows] => 0 [type] => 0
)
How do I fix this?
Code
if(isset($_POST["Logsub"])){
if(!empty($_POST["username"]) && !empty($_POST["password"])){
$username = filter_var($_POST["username"], FILTER_SANITIZE_STRING);
$password_sanitized = filter_var($_POST["password"], FILTER_SANITIZE_STRING);
$password = hash( "sha256", $password_sanitized ); //"sha256" is a type of hashing algorithm
if(preg_match("/^[a-zA-Z0-9]+$/", $username)&& preg_match("/^[a-zA-Z0-9]+$/", $password)){
$query = "SELECT * FROM login WHERE username = ? AND password = ?";
$stmt = $mysqli->stmt_init();
if ($stmt->prepare($query)) {
$stmt->bind_param('ss', $username, $password );
$stmt->execute();
//Returns a resultset for successful SELECT queries, or FALSE
$result = $stmt->get_result();
//If results (query for username and password that was entered) returns false
if(!$result) {
echo "<div class = 'message'> Invalid username or password. Please try again </div>";
} else {
echo "<div class = 'message'> You Have Been Successfully Logged In. </div>";
}
}
$stmt->close();
}
}
}
Database
`login` (`username`, `password`) VALUES (username, 'someHashedPassword');
get_results returns FALSE when it fails, otherwise it returns the dataset asked in the prepared statement. You are getting 0 rows, meaning that there is no user with such username and password. You are relying on FALSE instead of 0 rows to show that username or password is incorrect, which is wrong. It will only return FALSE if there was any error executing the prepared statement.
If you are concerned about why 0 results are returning and expect correct login, it can happen if the calculated hash of your password is not matching the hash which is stored in database.
Un-filtered approach:
if(isset($_POST["Logsub"]) && !empty($_POST["username"]) && !empty($_POST["password"])){
$username=$_POST["username"];
$password=hash("sha256",$_POST["password"]);
$query="SELECT * FROM login WHERE username=? AND password=?";
if($stmt=$mysqli->prepare($query)){
if($stmt->bind_param('ss',$username,$password) &&
$stmt->execute() &&
$stmt->store_result()
){
if($result=$stmt->get_result()){
echo "<div class=\"message\">You have been successfully logged in.</div>";
}else{
echo "<div class=\"message\">Invalid username or password. Please try again.</div>";
}
}else{
echo "Statement Error: ",$stmt->error; // do not echo when public
}
$stmt->close();
}else{
echo "Prepare Error: ",$mysqli->error; // do not echo when public
}
$mysqli->close();
}else{
echo "Insufficient or invalid credentials submitted";
}
You can combine your two initial condition statements into one.
You are likely damaging the password value while filtering/sanitizing. You can trust your prepared statement to keep your query safe from injection; all of that pre-filtering is unnecessary.
$stmt = $mysqli->stmt_init(); is in the manual but prepared statements will work without it (most people just put the dbh directly on prepare; this is my preference).
I have batched all of the stmt actions into one condition statement. If any of the conditions fail, php will immediately go to else condition and display the error.
I declared $result just in case you want to use it in your actual project.
If this code block doesn't permit login with the correct credentials, please echo out your $query, $username, and hash'ed $password glue it all together and run it directly on your database to ensure that it does/can match a row.
(*I did not test this code before posting)
I am having a problem with my update query when users request a password reset.
It simply does nothing, It does show that the password has been reset according to the alert command, but the database does not reflect the update...
Any assistance would be great as I cannot see where I am going wrong...
if(isset($_GET["acc"]) && isset($_GET["np"])){
$acc=decrypt(htmlspecialchars($_GET["acc"]));
$np=decrypt(htmlspecialchars($_GET["np"]));
//var_dump($acc);
//var_dump($np);
$query="UPDATE `master_profile` SET `password`=? where `email_address`=?";
if ($stmt = $connection_link->prepare($query)){
// Bind the variables to the parameter as strings.
$stmt->bind_param("ss",$np,$acc);
// Execute the statement.
if($stmt->execute()){
?>
<script>
alert('Your password has been reset. Please login with your new password.');
</script>
<?
//echo "Updated {$stmt->affected_rows} rows";
}else{
echo '<h1>An Error Has Occoured. Please try again later.</h1>';
}
if ($stmt->errno) {
echo "FAILURE!!! " . $stmt->error;
}
// Close the prepared statement.
$stmt->close();
}
}
Update
Changed if($stmt->execute(array($np,$acc))){} as suggested below but it simply gives me an error An Error Has Occoured. Please try again later., How can i catch this error and report the proper error?
I have tried $stmt->error; and $connection_link->error; but both just give an empty value.
Because you are using anonymous placeholders I think you need to omit your bind statement. Instead you would place the parameters in the execute as an array and in order of appearance in the statement
if($stmt->execute(array($acc, $np)){}
You would omit this line
$stmt->bind_param("ss",$np,$acc);
This should be easy but I'm can't make it work.
The idea is to look for an email adress posted from a form. If it exists echo something and if not echo something else.
My code is:
<?php
//MySQL Database Connect
mysql_connect("localhost", "********", "**********")
or die("Unable to connect to MySQL");
//get data from form
$email=$_POST['email'];
//ask the database for coincidences
$result = mysql_query("SELECT email FROM pressmails WHERE email='.$email.'");
$num_rows = mysql_num_rows($result);
if($num_rows < 0){
echo "The user is registered";
} else {
echo "The user is not registered";
}
//Close database connection
mysql_close();
?>
You are not concatenating string properly.
$result = mysql_query("SELECT email FROM pressmails WHERE email='.$email.'");
should be
$result = mysql_query("SELECT email FROM pressmails WHERE email='".$email."'");
You should end the string by using a closing quote (if you started the string with " you must end the string with " too, same for ').
And do not forget to use mysql_real_escape_string, otherwise the script is not safe.
The script will become something like this:
// save the query in a variable, so we can echo it to debug when it doesn't work as expected
$sql = "SELECT email FROM pressmails WHERE email='".mysql_real_escape_string($email)."'";
$result = mysql_query($sql);
You do not need the concatenation identifiers, since wrapping a literal in " will automatically parse variables into the string:
$result = mysql_query("SELECT email FROM pressmails WHERE email='$email'");
You should watch out, mind you. Doing the above represents a significant SQL injection vulnerability. You should consider sanitizing $email as a minimum. Also see my comment about the mysql_* functions in PHP.
From the Docs:
This extension is deprecated as of PHP 5.5.0, and will be removed in
the future. Instead, the MySQLi or PDO_MySQL extension should be used.
See also MySQL: choosing an API guide and related FAQ for more
information. Alternatives to this function include:
mysqli_close() PDO: Assign the value of NULL to the PDO object
(assuming you get your syntax errors corrected) isn't the logic of this backwards?
if($num_rows < 0){
echo "The user is registered";
} else {
echo "The user is not registered";
}
if the user is registered their email is in the database and the query returns one or more rows
try
if($num_rows){
echo "The user is registered";
} else {
echo "The user is not registered";
}
i have this code but i got two errors. I put in the comments the errors
if(!empty($_POST['email']) && validateEmail($email)) {
$email = $_POST["email"];
if ($sql = $db->prepare("select email from users where email=?")) {
$sql->bind_param('s', $email);
$sql->execute();
$sql->bind_result($email);
while ($sql->fetch()) {
$salt = "PiuwrO1#O0rl#+luH1!froe*l?8oEb!iu)_1Xaspi*(sw(^&.laBr~u3i!c?es-l651";
$password = md5($salt . $userExists["email"]);
$pwrurl = "www.yoursite.com/reset_password.php?q=" . $password;
$mailbody = "Dear user,<br><br>If this e-mail does not apply to you please ignore it. It appears that you have requested a password reset at our website www.yoursitehere.com<br>
To reset your password, please click the link below. If you cannot click it, please paste it into your web browser's address bar.<br> <a href='$pwrurl'>$pwrurl</a> <br> <br>
Thanks,\nThe Administration";
$mail->MsgHTML($mailbody);
$mail->AddAddress("dxxb#hotmail.com","Nome da Pessoa");
$mail->IsHTML(true);
if(!$mail->Send()) {
echo "Deu erro: " . $mail->ErrorInfo;
} else {
echo "Enviado com sucesso";
}
}
$sql->close();
$db->close();
}
($sql = $db->prepare('insert into password_reset (code) values (?)')); // Warning: mysqli::prepare() [mysqli.prepare]: Couldn't fetch mysqli in
$sql->bind_param('s', $password); // Fatal error: Call to a member function bind_param() on a non-object
$sql->execute();
$sql->fetch();
$sql->close();
$db->close();
}
all code works fine, but now i need to insert the salt in the db but i can't, and i don't know why
thanks
Edited code to the last version
After you execute a query, fetch returns one result. There may be more -- there may be many, many more -- so you should be calling fetch in a loop to get them all. You aren't supposed to prepare a new query until you've finished dealing with the old one, which would usually mean fetching every row of the result and closeing (in your case) $sql. Otherwise, the database is still in the middle of answering one request when you're trying to issue another one.
The first error says it all - you can't have more than 1 prepared statement/query "in flight" at once. You've not finished fetching data from the first query (select email ...) when you tried to prepare another statement (insert into ...).