Basic Logon with password hash [duplicate] - php

This question already has answers here:
mysqli_stmt::bind_result(): Number of bind variables doesn't match number of fields in prepared statement
(2 answers)
Closed 1 year ago.
I'm trying to learn the logon coding and below in the 1st attempt it was working fine except I realize I could just use a userID login and any other password to login successfully.
I try to strengthen the logon process in the 2nd attempt but encounter the error message below. I couldn't figure out where I'm getting it wrong.
There is the $username & $passWD using filter_has_var to get the data from logon form. It's not shown below in the codes.
Warning: mysqli_stmt_bind_result(): Number of bind variables doesn't match number of fields in prepared statement
1st attempt:
<?php
$username = filter_has_var(INPUT_POST, 'userName') ? $_POST['userName']: null;
$passWD = filter_has_var(INPUT_POST, 'pwd') ? $_POST['pwd']: null;
include 'database_conn.php'; // make db connection
$sql = "SELECT passwordHash FROM users WHERE username = ?";
$stmt = mysqli_prepare($conn, $sql); // prepare the sql statement
mysqli_stmt_bind_param($stmt, "s", $username);
mysqli_stmt_execute($stmt); // execute the query
mysqli_stmt_bind_result($stmt, $passWDHash);
if (mysqli_stmt_fetch($stmt)) {
password_verify($passWD, $passWDHash);
echo "<p>Login successful</p>";
}
else {
echo "<p>Please try again.</p>";
}
mysqli_stmt_close($stmt);
mysqli_close($conn);
?>
2nd attempt:
<?php
$username = filter_has_var(INPUT_POST, 'userName') ? $_POST['userName']: null;
$passWD = filter_has_var(INPUT_POST, 'pwd') ? $_POST['pwd']: null;
include 'database_conn.php'; // make db connection
$sql = "SELECT * FROM users WHERE username = ? AND passwordHash =?";
$stmt = mysqli_prepare($conn, $sql); // prepare the sql statement
mysqli_stmt_bind_param($stmt, "ss", $username, $passWD);
mysqli_stmt_execute($stmt); // execute the query
mysqli_stmt_bind_result($stmt, $username, $passWDHash);
if (mysqli_stmt_fetch($stmt)) {
password_verify($passWD, $passWDHash);
echo "<p>Login successful</p>";
}
else {
echo "<p>Sorry please try again.</p>";
}
mysqli_stmt_close($stmt);
mysqli_close($conn);
?>

using the wildcard * is not recommend. probably there are more columns in the table than just the 2 you need?
maby something like:
SELECT username,passwordHash FROM users WHERE username = ? AND passwordHash =?

Related

My DB password and user filled-in password, do not match [duplicate]

This question already has answers here:
How to use PHP's password_hash to hash and verify passwords
(5 answers)
Closed 2 years ago.
I've a problem with my php login file. I ask the password from my db by checking the email. When I obtain this password I check it with the password the user filled in.
In the password_verify($Passwd, $row['Passwd']) the result will always return 0 but the result should be return 1 (password matches).
Why do my passwords not match with each other?
Login code:
<?php
if(isset($_POST['submit'])){
include_once '../includes/connection.php';
$Email = $_POST['email'];
$Passwd = $_POST['passwd'];
//Create Template
$sql = "SELECT Passwd FROM user WHERE Email = ?";
//Create Prepared Statement
$stmt = mysqli_stmt_init($conn);
//Prepare Prepared Statement
if(!mysqli_stmt_prepare($stmt, $sql)){
echo "SQL Statement Failed";
} else {
mysqli_stmt_bind_param($stmt, "s", $Email);
mysqli_stmt_execute($stmt);
$res = mysqli_stmt_get_result($stmt);
while ($row = mysqli_fetch_assoc($res)){
echo $Passwd . "<br>";
echo $row['Passwd'];
if(password_verify($Passwd, $row['Passwd'])){
echo "1";
} else {
echo "0";
}
}
}
} else {
header("Location: ../index.php?login=error");
}
?>
Registration code:
<?php
if(isset($_POST['submit'])){
include_once '../includes/connection.php';
$Username = $_POST['username'];
$Email = $_POST['email'];
$Passwd = $_POST['pwd'];
//Create Template
$sql = "INSERT INTO user (Username, Email, Passwd)
VALUES (?, ?, ?);";
//Create Prepared Statement
$stmt = mysqli_stmt_init($conn);
//Prepare Prepared Statement
if (!mysqli_stmt_prepare($stmt, $sql)) {
echo "SQL Statement Failed";
} else {
$hashed_passwd = password_hash($Passwd, PASSWORD_DEFAULT);
//Replace '?' by the acctual data
mysqli_stmt_bind_param($stmt, "sss", $Username, $Email, $hashed_passwd);
//Run parameters inside database
mysqli_stmt_execute($stmt);
}
header("Location: ../index.php?signup=succes");
} else {
header("Location: ./index.php?sinup=error");
}
?>
Passwd is a varchar(50) column in the database.
The password_hash manual says:
it is recommended to store the result in a database column that can expand beyond 60 characters (255 characters would be a good choice)
So you need to specify a minimum size of 60 characters for the password column in your database - but a larger size e.g. 255 is recommended in case the default hashing algorithm changes in future.
You'll also need to re-generate any existing passwords stored in the 50-character field, because they will have been truncated when they were saved, and the extra information has been lost, meaning those old passwords can never be verified.

Number of variables doesn't match number of parameters - Trying to INSERT new data & updating current user data

I was following a tutorial on updating and insert information into databases.
I want to be able to insert additional information into the current user like company and website while also allowing them to update current user information such as first name and last name thats on file. Can this be possible? Any help would be appreciated.
<?php
// Initialize the session
session_start();
// Check if the user is logged in, if not then redirect to login page
if(!isset($_SESSION["loggedin"]) || $_SESSION["loggedin"] !== true){
header("location: login.php");
exit;
}
// Include config file
require_once "config.php";
// Define variables and initialize with empty values
$company = $website = "";
$company_err = $website_err = "";
$firstname = $lastname = "";
$firstname_err = $lastname_err = "";
// Processing form data when form is submitted
if($_SERVER["REQUEST_METHOD"] == "POST"){
// Validate email/username
if(empty(trim($_POST["company"]) && ($_POST["website"]))){
$company_err = "Please enter your company.";
$website_err = "Please enter a website.";
} else{
// Prepare a select statement
$sql = "SELECT id FROM users WHERE email = ?";
if($stmt = mysqli_prepare($link, $sql)){
// Bind variables to the prepared statement as parameters
mysqli_stmt_bind_param($stmt, 'ss', $param_company, $param_website);
// Set parameters
$param_company = trim($_POST["company"]);
$param_website = trim($_POST["website"]);
// Attempt to execute the prepared statement
if(mysqli_stmt_execute($stmt)){
/* store result */
mysqli_stmt_store_result($stmt);
$company = trim($_POST["company"]);
$website = trim($_POST["website"]);
} else{
echo "Oops! Something went wrong. Please try again later.";
}
}
// Close statement
mysqli_stmt_close($stmt);
}
// Check input errors before inserting in database
if(empty($company_err) && empty($website_err)){
// Prepare an insert statement
$sql = "INSERT INTO users (company, website) VALUES (?, ?)";
if($stmt = mysqli_prepare($link, $sql)){
// Bind variables to the prepared statement as parameters
mysqli_stmt_bind_param($stmt, "ss", $param_company, $param_website);
// Set parameters
$param_company = $company;
$param_website = $website;
// Attempt to execute the prepared statement
if(mysqli_stmt_execute($stmt)){
// Redirect to login page
header("location: welcome.php");
} else{
echo "Something went wrong. Please try again later.";
}
}
// Close statement
mysqli_stmt_close($stmt);
}
// Check input errors before updating the database
if(empty($firstname_err) && empty($lastname_err)){
// Prepare an update statement
$sql = "UPDATE users SET firstname, lastname = ? WHERE id = ?";
if($stmt = mysqli_prepare($link, $sql)){
// Bind variables to the prepared statement as parameters
mysqli_stmt_bind_param($stmt, "sse", $param_firstname, $param_lastname, $param_id);
// Set parameters
$param_firstname = trim($_POST["firstname"]);
$param_lastname = trim($_POST["lastname"]);
$param_id = $_SESSION["id"];
// Attempt to execute the prepared statement
if(mysqli_stmt_execute($stmt)){
// Updated successfully. Redirect to welcome page
header("location: welcome.php");
} else{
echo "Oops! Something went wrong. Please try again later.";
}
}
// Close statement
mysqli_stmt_close($stmt);
}
// Close connection
mysqli_close($link);
}
?>
$sql = "UPDATE users SET firstname, lastname = ? WHERE id = ?";
Should be...
$sql = "UPDATE users SET firstname = ?, lastname = ? WHERE id = ?";

"Cant process the request", dealing with basic parameterized queries

I am trying something I found online (Extremely new to this) and none of it works. It's some random science project I decided to learn more about yet I am stuck on part 2 of the "procedures". https://www.sciencebuddies.org/science-fair-projects/project-ideas/Cyber_p008/cybersecurity/sql-injection#procedure
I watched videos but they only consist of just a user_ID and not a username and password. NOTE: Only the code dealing with login.php is causing problems.
<?php
include("global.php");
include("db.php");
session_start();
if ($_SERVER["REQUEST_METHOD"] == "POST") {
// username and password are sent in the form
$username = $_POST['username'];
$password = $_POST['password'];
// Check if the username and password exist in the database
$sql = "SELECT username FROM users WHERE username = '$username' AND password = '$password'";
$stmt = msqli_stmt_init($db);
if (!mysqli_stmt_prepare($stmt, $sql)) {
echo "SQL Statement Failed";
} else {
mysqli_stmt_bind_param($stmt, "ss", $username, $password );
mysqli_stmt_execute($stmt);
$result = mysqli_stmt_get_result($stmt);
$row = mysqli_fetch_array($result, MYSQLI_ASSOC);
$count = mysqli_num_rows($result);}
// If username and password matched then there is one row in the result
if ($count != 0) {
$_SESSION['login_user'] = strtolower($username);
header("location: search.php");
}
else {
$error = "Your Username or Password is invalid";
}
}
?>
It should have prevented a basic " 'or''=' " injection attack but it decided not to work entirely.
If you use query parameters — which is definitely a good idea — you must leave placeholders in your query. Use ? as the placeholder.
Like this:
$sql = "SELECT username FROM users WHERE username = ? AND password = ?";
You later bind variables to those parameters. You must bind the same number of variables as the number of parameter placeholders.
You got the error you described because you tried to bind variables to a query that had no parameter placeholders.

My reset password password system gives me a a data base error

I have been trying to make a reset password system where my code is as follows:
<?php ob_start();
include "includes/header.php";
include "includes/db.php";
//session_start();
include "includes/navigation.php";
if(isset($_GET['reset']) && isset($_GET['token'])) {
$token = $_GET['token'];
$stmt = mysqli_prepare($connection, "SELECT username, user_email, token FROM users WHERE token=?");
mysqli_stmt_bind_param($stmt, "s", $token);
mysqli_stmt_execute($stmt);
mysqli_stmt_bind_result($stmt, $username, $user_email, $token);
mysqli_stmt_fetch($stmt);
if(!empty($username)) {
if(isset($_POST['password']) && isset($_POST['confirmPassword']) && $_POST['password'] == $_POST['confirmPassword']) {
$password = $_POST['password'];
$hashedPassword = password_hash($password, PASSWORD_BCRYPT, array('cost'=>12));
echo $hashedPassword;
echo $user_email;
$stmt = mysqli_prepare($connection, "UPDATE users SET token= '', user_password= '{$hashedPassword}' WHERE user_email= ?");
mysqli_stmt_bind_param($stmt, "s", $user_email);
mysqli_stmt_execute($stmt);
}
} else {
header("Location: index.php");
}
} else {
header("Location: index.php");
}
?>
Now the case is that the first query is working well. The token is inserted successfully in the database to the account requesting to the reset password and it successfully got the data from the database.
The issue comes when the new password and its confirmation are inserted by the user. Although the password is hashed successfully, there is a problem inserting it into the database.
It got me the "mysqli_stmt_bind_param() expects parameter 1 to be mysqli_stmt, boolean given". For sure the problem is not in the connection as the connection already worked in the above query. I have been going around checking what is wrong with the statementquery but I cannot recognize any mistake.
Appreciate your help.
Thanks
I have amended your code and documented as best where possible where you have went wrong, and why my corrections should work.
<?php ob_start();
include "includes/header.php";
include "includes/db.php";
//session_start();
include "includes/navigation.php";
if(isset($_GET['reset']) && isset($_GET['token'])) {
$token = $_GET['token'];
//I have amended your query, you do not need to grab the token if the condition is that it is the same as something you already have, as $_GET['token'] AND $token will always be the same.
$query = "SELECT username, user_email FROM users WHERE token = ?");
$stmt = $connection->prepare($query);
$stmt->bind_param("s", $_GET['token']);
$stmt->execute();
$stmt->bind_result($username, $user_email);
$stmt->fetch();
$stmt->close(); // You did not close your query connection.
// To use a new query you must first close the previous one.
if(!empty($username)) {
if(isset($_POST['password']) && isset($_POST['confirmPassword']) && $_POST['password'] == $_POST['confirmPassword']) {
$password = $_POST['password'];
$hashedPassword = password_hash($password, PASSWORD_BCRYPT, array('cost'=>12));
echo $hashedPassword;
echo $user_email;
// Previously you tried to insert a PHP variable into a query, which is not possible
// in (and defeats the point of) prepared statements. Rather than put in $variable
// replace them with '?' . (not including quotation marks)
$query = "UPDATE users SET token = null, user_password = ? WHERE user_email = ?";
$stmt = $connection->prepare($query);
$stmt->bind_param("ss", $hashed_password, $user_email);
$stmt->execute();
$stmt->close();
}
} else {
header("Location: index.php");
}
} else {
header("Location: index.php");
}
Additionally, your output buffering at the beginning of the document can most likely be avoided if you place your db.php before your header, and also the code I've provided before your header. (This is just based on some errors I've seen in other's code.)
The error you described in your original post "mysqli_stmt_bind_param() expects parameter 1 to be mysqli_stmt" means that most likely there is an error in the query syntax, which is the main element I have amended.

mysqli_stmt::bind_result(): error [duplicate]

This question already has answers here:
mysqli_stmt::bind_result(): Number of bind variables doesn't match number of fields in prepared statement
(2 answers)
Closed 1 year ago.
hi i've been using php for a while now but i'm still quiet new to a few things one of which is the bind_result(). So i'm creating a login system on a project but i keep getting the error:
mysqli_stmt::bind_result(): Number of bind variables doesn't match number of fields in prepared statement
i know this is to do with the fact that i'm selecting all the columns, what i want to know do i have to bind all of the columns or is their an easier way?
my code in function.php
public function getUserByEmailAndPassword($email, $password) {
$sql = "SELECT * FROM users WHERE email = ?"; // SQL Statement
$stmt = $this->conn->prepare($sql); // Prepare the SQL Statement
$stmt->bind_param('s', $email); // Bind the placeholder with the correct data type from the SQL Statement
$stmt->execute(); // Execute the prepared statement
$stmt->store_result(); // Store the prepared statement for later checking
// Check to make sure if any data is returned
if($stmt->num_rows) {
// Create and append variables
$user = $stmt->bind_result($email);
// Create a while loop
while($stmt->fetch()) {
// verifying user password
$salt = $user['salt'];
$encrypted_password = $user['encrypted_password'];
$hash = $this->checkhashSSHA($salt, $password);
// check for password equality
if ($encrypted_password == $hash) {
// user authentication details are correct
$stmt->close();
return $user;
}else {
}
}
return NULL;
}
}
You can try this code. But as your query is not clear please encrypt your password and then check in if condition
function getUserByEmailAndPassword($email) {
$stmt = $conn->prepare('SELECT
email,
password
FROM users
WHERE email = ?
');
$stmt->bind_param('s',$email);
$stmt->execute();
$stmt->store_result();
while($stmt->fetch()){
$row = array('email'=>$email,'password'=>$password);
}
$stmt->close();
if(!empty($row)){
return $row;
} else {
return "";
}
}
$userDetails = getUserByEmailAndPassword($email);
//Encrypt your password here
if($userDetails['password'] == $encryped_password){
//do_something
}

Categories