Count function is not working properly for sql's result - php

I wrote code for sign up where I check username , if it is exists in database or not than add new user accordingly. I am new to sql->prepare statement, Problem is in count function , when checking username it works properly, but in else part when adding user it gives me following error
Uncaught TypeError: count(): Argument #1 ($value) must be of type
Countable|array, bool
Here is my adduser.php code.
<?php
include 'config.php';
//checkusername
$check = $con->prepare("select username from users where username = ?");
$check->bindParam(1,$username);
$username = $_POST['username'];
$check->execute();
$row = $check->fetch(PDO::FETCH_ASSOC);
if(count($row)){
echo -1;
}
else{
$sql = $con->prepare("insert into users(name,username,password) values(?,?,?)");
$sql->bindParam(1,$name);
$sql->bindParam(2,$username);
$sql->bindParam(3,$password);
$name = $_POST['name'];
$username = $_POST['username'];
$password = md5($_POST['password']);
$sql->execute();
echo 1;
}
?>

It doesn't make much sense to use count here, you don't need to know how many fields are in the row.
Just check if it's false or not - see php.net/manual/en/pdostatement.fetch.php which mentions that fetch() will return false when it fails (i.e. there is no row available).
This would make more sense:
if($row) {
$sql = $con->prepare("insert into users(name,username,password) values(?,?,?)");
//...etc...
}
else {
echo -1;
}

After executing the query with $check->execute();, you can use the built-in method to count the returned rows: $check->rowCount();.
I think the statement above returned 0 rows, so you can't do $check->fetch() and it returns false.
Example:
// Your code here...
$check = $con->prepare("select username from users where username = ?");
$username = $_POST['username']; // This line needs to be before the next one, because you used the variable $username before defining it
$check->bindParam(1,$username);
$check->execute();
if($check->rowCount() > 0) {
// User does exist
} else {
// User does not exist
}

Edit 2: I just realised that the answer I've given below is wrong. The thing I suggest instead is checking if there's any value by using the PDO rowCount() method, like this: if ($check->rowCount()>0)
wrong stuff below
You're assigining $username a value after binding it.
$check = $con->prepare("select username from users where username = ?");
$check->bindParam(1,$username); //bind $username
$username = $_POST['username']; //assign value
$check->execute();
Try switching those two lines so $username is assigned a value when you're binding it.
$check = $con->prepare("select username from users where username = ?");
$username = $_POST['username']; //assign value
$check->bindParam(1,$username); //bind $username
$check->execute();
Edit
In case you're still having issues, try checking if there's any error in the sql statement execution.
After your $check->execute(); you can add print_r($check->errorInfo()); to see if your MySQL statement has any issues in it.

Related

How to make php to redirect each user to their own respective pages?

ok, so i have a little issue here with php. I know there are alot of similar questions, but ones i found did not help.
I dont want to use anything more like javascript or something. I got mysql set up, there are 3 columns ID username and password.
<?php
$username = $_POST['user'];
$password = $_POST['pass'];
$username = stripcslashes($username);
$password = stripcslashes($password);
$username = mysql_real_escape_string($username);
$password = mysql_real_escape_string($password);
mysql_connect("localhost","root","");
mysql_select_db("login");
$result = mysql_query("select * from users where username='$username' and password= '$password'")
or die("failed to query DB".mysql_error());
$row = mysql_fetch_array($result);
if ($row['username'] == $username && $row['password'] == $password) {header(suc.html);
die();}else{header("Location: fail.html");die();}
?>
This code, it works but when i dont fill in any details and press submit too, it gets me to the suc.html which shows successful login. Now i want to make the following:
I'll make ID's similar to each individual html's names, then the php will go match the ID number with the file name in the directory, and show the page for the respective user.
like lets say user1.
Login userlol password 123 ID user1 file user1.html
then what code to use that it goes and matches the ID user1 with the .html name, then redirects the user to their own custom page. Is there a way? Kinda getting started with php ,so cut some slack please :)
p.s i know these codes are older php codes, but anything works for me personally.
You are getting that sort of behaviour because when a username and password is not submitted, their respective values evaluates to null and your SQL query is successful but returns 0 rows thereby making your $row['username'] and $row['password'] to be null. In general, your $row['username'],$row['password'],$username,$password would all be equal to null which fulfills all the requirements to redirect to "suc.html"
To solve this problem, simply check if mysql_num_rows($result)==1 because usually, a successful login would return just one row due to unique usernames.
But
I would not advice you to continue with deprecated mysql and SQL Injection susceptible logic. Please allow me to rewrite your logic as follows:
<?php
$username = $_POST['user'];
$password = $_POST['pass'];
// You don't have to escape or sanitize user inputs if you use Prepared Statement plus sanitizing user password is highly discouraged.
// $username = stripcslashes($username);
// $password = stripcslashes($password);
// $username = mysql_real_escape_string($username);
// $password = mysql_real_escape_string($password);
// Initiate a PDO connection and set your error mode to exception.
$conn=new pdo("mysql:host=localhost;dbname=login;","root","",array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION));
try{
// Prepare your query and replace all values with ? which would be provided as an array in execute(); I added limit 1 to make sure we are getting a maximum of one row from our query.
$result_stmt = $conn->prepare("select * from `users` where (`username`=? and `password`=?) limit 1");
$result_stmt->execute([$username,$password]);
// fatch() would return a single row just like mysql_fetch_array or mysql_fetch_assoc while fetchAll() would return all rows.
$result=$result_stmt->fetch();
if(count($result)==1){
// There is no need to check this again because your query to the database already did.
// if ($row['username'] == $username && $row['password'] == $password)
// Redirect users to the same page but identify each user through session (recommended)
header("location:suc.html");
}else{
header("location:fail.html");
}
}catch(Exception $e){
echo $e->getMessage();
}
?>

Name and password individual check in PHP

I am writing a deliberately vulnerable web application. I'd like to figure out how to check username and password, matching against the database and each other as well.
So: if the username exists in the database and the password exists in the database and the username and password belongs together. I'm fully aware how to send a query which checks for both at the same time and returns either true or false, so please don't start on that. My goal is to individually check for both so I can inform the user which one is not working.
Here's my code but as I'm not really a PHP person this is obviously not working:
<?php
if(isset($_POST["submit"])){
$username = mysqli_real_escape_string($conn, $_POST['username']);
$password = mysqli_real_escape_string($conn, $_POST['password']);
$sql_username = "SELECT id FROM users WHERE username = '$username'";
$sql_password = "SELECT id FROM users WHERE password = '$password'";
$result_username = mysqli_query($conn, $sql_username);
$result_password = mysqli_query($conn, $sql_password);
$row_username = mysqli_fetch_array($result_username);
$row_password = mysqli_fetch_array($result_password);
$count_username = mysqli_num_rows($result_username);
$count_password = mysqli_num_rows($result_password);
if($count_username > 0 && $count_password < 0) {
echo "Invalied password";
} else if ($count_username < 0 && $count_password > 0) {
echo "Invalied username";
} else {
"Welcome";
}
}
?>
Any hints?
Edit
$conn can be used as I'm getting it from another php file.
<?php
//set up a connection and all that prerequisite stuff
$sqlConnectionNameHere = new mysqli($sql_host, $sql_username, $sql_password, $sql_dbname);
$username = 'bob'; //the username that will be checked
$password = 'securepassword1'; //the password that will be checked
$query = $sqlConnectionNameHere->query("SELECT username, password FROM users WHERE username='$username' LIMIT 1"); //make your query
if ($query->num_rows != 1){ //if the datbase didn't return any rows, the user with $username must not exist
die('User not found!');
}
while ($user = $query->fetch_assoc()){
if ($user['password'] != $password){
die('Invalid Password');
}
}
//if they've made it here, the user exists and the password matches!
echo 'Welcome!';
?>
This is a really barebones way of doing it. You may want to add more security to this.
Hope this helps. Best of luck to you!
I know its way cooler to let the user know wether the username or password is wrong. But this actually helps get unwanted indivuduals to pass this test. Since they can test if a specific user is present or not. From there this individual would bruteforce the password. So its a good practice to just check for username AND password.
Furthermore you can store the password as a hash. This way not even the hoster of your db has a direct access to the passwords. Use MD5 or SHA. As example the credentials in your db would look like:
User Password
Admin 098f6bcd4621d373cade4e832627b4f6
This is a MD5 hash. You'll get this hash if you process md5('test'). A hash is a one way "encryption" function. You check it by hashing the user-input and comparing this result with the stored hash.
If you check for this password you'd bind it like this:
$stmt->bind_param("ss", $_POST['username'], md5($_POST['password']));
$mysqli = new mysqli("localhost", "my_user", "my_password", "my_db");
Plaintext password(not recommended!) - prepared select
$stmt = $mysqli->prepare("SELECT id FROM users WHERE username=? AND password=?");
// type string, string ("ss")
$stmt->bind_param("ss", $_POST['username'], $_POST['password']);
// hashed (recommended)
// $stmt->bind_param("ss", $_POST['username'], md5($_POST['password']));
$stmt->execute();
// set target for the id-column
$stmt->bind_result($id);
// Will be TRUE if a row has been found
if( $stmt->fetch() ) {
echo "Welcome! user:{$id}";
} else {
echo "Invalid username or password";
}
For details have a look at mysqli prepare
And a little more security related: Password hashing

Keep getting mysqli_free_result() expects parameter 1 to be mysqli_result, null given

Working on a log in system, but i keep getting this error
//$User = 'kv96';
//$Pass = 'passkv';
//echo isValidLogin($User, $Pass);
function isValidLogin($username, $password) {
$query = mysqli_query($link,"SELECT * FROM Log_in WHERE Password = '$Pass' AND User_ID ='$User'"); //Finds the database and chooses the row
//$result = mysqli_query($query);
$row = mysqli_fetch_array($result); //Fetches the row
if($row['User_ID'] != null && $row['Password'] != null){return true;}
else{return false;}
function getUsernameRole($username) {
return "instructor";
}
mysqli_close($link);
?>
Can someone explain why this error is popping, i dont see why the query is failing?
I've noticed you commented out your $result yet you were using to fetch the database array. You should be using $query instead, or get rid of the 2 // before your $result.
Not only that, you forgot to parse $link through the parameters of your function. Therefore the query will not be successful.
Another problem, you used $pass and $user variables inside of your query, however, you have not passed them through the parameters of your function either. You must change $username to $user and so on..
I've also changed your while loop to a row count. This will save you from using unnecessary code and is way more practical; saves you doing a while loop and checking if values return null.
function isValidLogin($link, $user, $pass) { // parsing through the connection link and $user, $pass variables
$query = mysqli_query($link,"SELECT * FROM Log_in WHERE Password = '$Pass' AND User_ID ='$User'"); //Finds the database and chooses the row
$count = mysqli_num_rows($query);
if($count > 0){
return true;
} else {
return false;
}
}
A suggestion I would like to make (and HIGHLY recommend) is to use prepared statements to protect against SQL injection, however, you can find many posts on how to do that.

Php log in allows entry with no user/pass

Hey guys ive put together a basic user log in for a secure admin area and it seems to work great, if you enter a correct user/pass you get access, if you enter the wrong user pass, you get no access. However if you enter nothing in both fields you get access.
This is how it works.
Creating a user, a basic form POSTS to this php file.
<?php
$con = mysqli_connect(credentials are all good) or die(mysqli_error($con)) ;
$escapedUser = mysqli_real_escape_string($con, $_POST['user']);
$escapedPass = mysqli_real_escape_string($con, $_POST['pass']);
$some_str = md5(uniqid(mt_rand(), true));
$base_64str = base64_encode($some_str);
$modified_base64 = str_replace('+', '.', $base_64str);
$gensalt = substr($modified_base64, 0, 22);
$format_str = "$2y$10$"; // 2y for Blowfish and 10 times.
$salt = $format_str . $gensalt . "$";
$hashed_pass = crypt($escapedPass, $salt);
$query = "INSERT INTO `userpass` (`username`, `password`, `salt`) VALUES ('$escapedUser', '$hashed_pass', '$salt'); ";
if(isset($escapedUser) && isset($hashed_pass))
{
mysqli_query($con, $query);
header("Location: ausers.php");
exit();
}
Echo "Something went wrong!";
?>
The database appears to be storing these fine
We then log in with this code
<?php
$con = mysqli_connect(again credentials are fine) or die(mysqli_error($con)) ;
$escapedUser = mysqli_real_escape_string($con, $_POST['user']);
$escapedPass = mysqli_real_escape_string($con, $_POST['pass']);
$saltQuery = "select salt from userpass where username = '$escapedUser';";
$result = mysqli_query($con, $saltQuery);
$row = mysqli_fetch_assoc($result);
$salt = $row['salt'];
$hashed_pass = crypt($escapedPass, $salt);
if(isset($escapedUser) && isset($hashed_pass))
{
$userQuery = "SELECT * FROM userpass WHERE username='$escapedUser' AND password='$hashed_pass'";
$userpass = mysqli_query($con, $userQuery);
$count = mysqli_num_rows($userpass);
if($count == 1)
{
$_SESSION['username'] = $escapedUser;
header("location: aindex.php");
exit();
}
header("Location: alogin.htm");
exit();
}
Echo "Something went wrong!";
?>
So as i said, this seems to work fine for when any user pass combination is given whether access granted or denied however using no user and pass and pressing log in allows entry. Any ideas? THeres no blank rows in the database table.
Side question, is this salt/hash method correct, its my first attempt.
For your login code, your condition relies on an isset() test. You perform this test on $escapedUser and $hashed_pass. Both of these variables were actually assigned values earlier in the code! Once you assign a value to the variable, it will pass the isset() test, even if the value is an empty string. You might want to use an empty() check, perhaps on the original $_POST variables.
Moving on to the inner condition, which tests if the mysql query returns exactly 1 row of results. If there were truly no rows with empty values, then this condition would never pass because the query would return 0 rows. But it is passing. Two things to consider:
Notice that your registering code uses the same isset() test. Therefore it is very possible that someone used your registration form, submitted empty fields, and successfully registered a row with empty user and password fields. Have you explicitly queried your database for empty fields and actually come up with 0 results?
Your query uses SELECT *. Perhaps this is causing the query to return some sort of aggregate value (like a COUNT() or something that always has a result no matter what). Perhaps try explicitly defining the columns to return?
I cannot comment on your salt/hash method as I have no experience in that part. Hope you find this helpful!
In my opinion you need more than one level of checks in any form, whether it be registration, comments, login, etc. The way I prefer to go about it is a tiered approach. It may work better for you, but it's just an example.
By doing it this way, you ensure that your input will never be empty. Another issue I see with your login script is that you never compare the input with the database so how can you know if they entered the correct information? The only thing allowing them to login is that the query returned a record. This is also why they can login with a blank form.
<?php
$con = mysqli_connect(again credentials are fine) or die(mysqli_error($con)) ;
/* Ensures that form was submitted before any processing is done */
if (isset($_POST)) {
$User = $_POST['user']);
$Pass = $_POST['pass']);
if (!empty($User)) {
if (!empty($Pass)) {
$escapedUser = mysqli_real_escape_string($con, $User);
$escapedPass = mysqli_real_escape_string($con, $Pass);
/* you need to verify the password here, before adding the salt */
$saltQuery = "select salt from userpass where username = '$escapedUser'";
$result = mysqli_query($con, $saltQuery);
$row = mysqli_fetch_assoc($result);
$salt = $row['salt'];
$hashed_pass = crypt($escapedPass, $salt);
$userQuery = "SELECT * FROM userpass WHERE username='$escapedUser' AND password='$hashed_pass'";
/* you need to verify the username somewhere here */
$userpass = mysqli_query($con, $userQuery);
$count = mysqli_num_rows($userpass);
if($count == 1)
{
$_SESSION['username'] = $escapedUser;
header("location: aindex.php");
exit();
} else {
header("Location: alogin.htm");
exit();
}
} else {
echo "Please enter a password.";
}
} else {
echo "Please enter a username.";
}
} else {
echo "You have not entered any information.";
}
?>

PHP/MySQL - Checking results

I'm trying to create a login system with PHP, but the SQL query is not returning the result I'm expecting.
I have a typical username and password page, and I'm using what the user types in there to check for an account. I know for a fact that the database contains real usernames and passwords but the call to mysqli_num_rows is always returning 0.
Is there something I'm doing wrong?
$username = $_POST['username'];
$password = $_POST['password'];
$result = mysqli_query($con, "SELECT * FROM StaffTable WHERE staffNo='$username' AND password='$password'");
echo mysqli_num_rows($result); //This always prints out 0.
if(mysqli_num_rows($result) == 1)
{
echo "OK";
}
Ignoring the plain-text-password thing which you claim to be aware of, something like this perhaps...
$username = isset($_POST['username']) ? $_POST['username'] : null;
$password = isset($_POST['password']) ? $_POST['password'] : null;
$stmt = $con->prepare('SELECT 1 FROM StaffTable WHERE staffNo = ? AND password = ?');
if (!$stmt) {
throw new Exception($con->error, $con->errno);
}
$stmt->bind_param('ss', $username, $password);
if (!$stmt->execute()) {
throw new Exception($stmt->error, $stmt->errno);
}
if ($stmt->fetch()) {
echo 'OK';
}
To summarise...
I've checked that the input variables are set and assigned defaults if they're not that shouldn't produce any false positives
I've used a prepared statement with bound parameters to avoid SQL injection vulnerabilities
I throw exceptions when errors occur. These are great because they halt execution and give you all the information you need to debug the problem.
This is my main problem with mysqli over PDO. mysqli is simply not noisy enough when errors occur. You shouldn't have to manually check for error conditions all the time.
I've changed the query to a simple boolean check as that's all you were using it for. The row either exists, or it doesn't.
Try something more along the lines of
$username=$_POST['username'];
$password=md5($_POST['password']);
$query="SELECT * FROM StaffTable WHERE staffNo='".$username."' AND password='".$password."'";
$result=mysqli_query($con,$query);
if (mysqli_num_rows($result)==0)
{
echo "Incorrect Password Or Username Combo";
}
else {
while($row=mysqli_fetch_object($result)) {
$_SESSION['id']=$row['id'];
}
I would say to start with at least running the passwords in encryption for now and look into SQL injection and upgrade as you learn more about what you're looking at.
The biggest flaw in yours aside from what's already been pointed out is
($con, "SELECT * FROM StaffTable WHERE staffNo='$username' AND password='$password'");
With the variables you cannot put them within the query that way; you would want to do something more along the lines of
($con, "SELECT * FROM StaffTable WHERE staffNo='".$username."' AND password='".$password."'");
If you'll notice I escaped from the plain text so that the variables would be set. The reason you're returning 0 results everytime is because you are actually searching for username $username with $password as their password.
Good luck!

Categories