PDO query works from CLI, not from PHP - php

I have a MySQL query which works from the command line, but not from PHP.
Can anyone see what I am doing wrong?
$sqlText = 'SELECT FROM customers WHERE login_name=:name
AND password=:password';
$query = $pdo->prepare($sqlText);
$query->bindParam(':name', $userName);
$query->bindParam(':password', sha1($password));
$result = $query->fetch(PDO::FETCH_ASSOC);
and $result is false.
But, from the command line,
SELECT * FROM customers WHERE login_name="a"
AND password="4192dee2f886e99ececbb2eee0d2f37f11257974"
works.
When I debug userName is a and $password is 4192dee2f886e99ececbb2eee0d2f37f11257974.
Can some one make me say D'oh ?

You've forgotten about execute I suppose:
$sqlText = 'SELECT FROM customers WHERE login_name=:name AND password=:password';
$query = $pdo->prepare($sqlText);
$hash = sha1($password);
$query->bindParam(':name', $userName);
$query->bindParam(':password', $hash);
$query->execute();
$result = $query->fetch(PDO::FETCH_ASSOC);

You forgot execute().
Moreover, if really $password` is `4192dee2f886e99ececbb2eee0d2f37f11257974, then you must be running sha1() twice. Either remove the sha1() from the bind line, or keep $password in the clear.
I'd suggest naming the database column "passwordHash", and the variable either $password if it is in cleartext, or $passwordHash if you already ran sha1() on it. That way, you would have written
$query->bindParam(':passwordHash', sha1($passwordHash));
and immediately spotted the extra sha1() call.

you have to call $query->execute(); to execute the query in PDO
$sqlText = 'SELECT FROM customers WHERE login_name=:name AND password=:password';
$query = $pdo->prepare($sqlText);
$query->bindParam(':name', $userName);
$query->bindParam(':password', sha1($password));
$query->execute();
$result = $query->fetch(PDO::FETCH_ASSOC);

The prepare method only prepares the sql statement you passed in and returns a preparedstatement object.
As mentioned above, you need to set the params and execute it to get the resultset back.
The advantages of prepared statement besides the security is that you can repeatedly assign parameters and execute a preparedstatement which is considered to be faster than compiling the same sql query string again and again.

Related

Update sql using bind param

I have a sql statement to update confirm code and code in the database. I'm using bind param to bind the variables. It worked fine for my select and insert sql statements. However, it keeps giving me this error:
Fatal error: Uncaught Error: Call to a member function bind_param() on boolean
when I tried to execute the update query. I tried to search on every forums possible but found no answers and I hope someone could maybe spot my mistake. I'm having issues with $query1. Both code and confirmcode are varchar and not integer.
$username = $_GET['username'];
$code = $_GET['code'];
$confirmcode = "1";
$updatecode ="0";
$query=$con->prepare("SELECT username, code FROM customer_detail WHERE username ='$username'");
$query->execute();
$query->bind_result($checkusername, $checkcode);
$query->fetch();
$query1=$con->prepare("UPDATE customer_detail SET code=?, confirmcode=? WHERE username = ?"); //error
$query1->bind_param('sss',$username, $updatecode, $confirmcode); //error
$query1->execute();
The problem is that MySQLi can't run multiple queries at once, because it uses ubuffered queries. You'll need to close the first statement before you can run another. Add the following line after $query->fetch();.
$query->close();
This being said, your first query isn't guarded against SQL injection, because you use the variable directly in the query. Adding proper placeholders for your query, the final code would look like this
$query = $con->prepare("SELECT username, code FROM customer_detail WHERE username =?");
$query->bind_param('s', $username);
$query->execute();
$query->bind_result($checkusername, $checkcode);
$query->fetch();
$query->close();
$query1 = $con->prepare("UPDATE customer_detail SET code=?, confirmcode=? WHERE username = ?");
$query1->bind_param('sss',$username, $updatecode, $confirmcode);
$query1->execute();
$query1->close();
Try below code. Basically, you need to bind the params in the same order in which the placeholders (?) appear in the sql.
$query=$con->prepare("SELECT username, code FROM customer_detail WHERE username = ?");
$query->bind_param('s', $username);
$query->execute();
$query->bind_result($checkusername, $checkcode);
$query->fetch();
$query1=$con->prepare("UPDATE customer_detail SET code=?, confirmcode=? WHERE username = ?");
$query1->bind_param('sss', $updatecode, $confirmcode, $username);
$query1->execute();
Have you tried tis?
$query1->bind_param('iis', $updatecode, $confirmcode, $username);

PDO Prepared Statements and MSSQL databases not functioning correctly

I'm having a problem running prepared queries on a MSSQL database using PDO. I can connect to the database and run SELECT queries with no parameters, but now I'm trying to run a simple SELECT query with one parameter, :user. However, the code does not return any values, despite the fact that there definitely is a database row with that value in. Here's the code I'm using:
$db = new PDO('dblib:host='.$dbHost.';dbname='.$dbName.';charset=utf8mb4',$dbUser, $dbPass);
$stmt = $db->prepare('SELECT * FROM customer WHERE email_address = :user ');
$stmt->bindValue(":user", $_SESSION["username"], PDO::PARAM_STR);
$result = $stmt->fetchAll(PDO::FETCH_ASSOC);
var_dump($result);
I receive no output from the var_dump. I know that in the database there is a correct row, so I tried:
$stmt = $db->prepare("SELECT * FROM customer WHERE email_address = 'the#email.com'");
$result = $stmt->fetchAll(PDO::FETCH_ASSOC);
var_dump($result);
And yet still no value was returned. Am I doing something wrong with PDO? If I type this exact query into the query bar it runs.
you forgot to execute your query.
right after the paramter binding, put this code:
$stmt->execute();
Ok, I'm an idiot. Forgot to execute the query. Amended code for people in the same predicament:
$db = new PDO('dblib:host='.$dbHost.';dbname='.$dbName.';charset=utf8mb4',$dbUser, $dbPass);
$stmt = $db->prepare('SELECT * FROM customer WHERE email_address = :user ');
$stmt->bindValue(":user", $_SESSION["username"], PDO::PARAM_STR);
$stmt->execute();
$result = $stmt->fetchAll(PDO::FETCH_ASSOC);
var_dump($result);

Query returning zero rows despite entries existing

I have these prepared statements below. I perform the execute and both return 1, meaning the query was successful, but num_rows is still zero. I don't know why. Any ideas?
$ustmt = $bd->prepare("SELECT * FROM member WHERE username = ?");
$ustmt->bind_param("s", $username);
$astmt = $bd->prepare("SELECT address FROM member WHERE address = ?");
$astmt->bind_param("s", $address);
$sql = $ustmt->execute();
$sql2 = $astmt->execute();
echo($sql2);
echo($sql);
echo($ustmt->num_rows);
echo($astmt->num_rows);
I had forgotten to add store_result(); after I had executed. I have wasted a lot of hours!

Which PDO bind approach should be used for greater security?

I know of two ways to use PDO in PHP to update a MySQL database record. Please could someone explain which one I should use for better security and the difference and I am a little confused.
Method One:
$user = "root";
$pass = "";
$dbh = new PDO('mysql:host=somehost;dbname=somedb', $user, $pass);
$sql = "UPDATE coupons SET
coupon_code = :coupon_code,
valid_from = :valid_from,
valid_to = :valid_to,
discount_percentage = :discount_percentage,
discount_amount = :discount_amount,
calculationType = :calculationType,
limit = :limit
WHERE coupon_code = :coupon";
$stmt = $dbh->prepare($sql);
$stmt->bindParam(':coupon_code', $_POST['coupon_code'], PDO::PARAM_STR);
$stmt->bindParam(':valid_from', $_POST['$valid_from'], PDO::PARAM_STR);
$stmt->bindParam(':valid_to', $_POST['valid_to'], PDO::PARAM_STR);
$stmt->bindParam(':discount_percentage', $_POST['discount_percentage'], PDO::PARAM_STR);
$stmt->bindParam(':discount_amount', $_POST['discount_amount'], PDO::PARAM_STR);
$stmt->bindParam(':calculationType', $_POST['calculationType'], PDO::PARAM_STR);
$stmt->bindParam(':limit', $_POST['limit'], PDO::PARAM_STR);
$stmt->bindParam(':coupon', $_POST['coupon_code'], PDO::PARAM_STR);
$stmt->execute();
Method Two:
$dbtype="somedbtype";
$dbhost="somehost";
$dbname="somedb";
$dbuser="someuser";
$dbpass= "somepass";
$conn = new PDO("mysql:host=$dbhost;dbname=$dbname",$dbuser,$dbpass);
$title = 'PHP Pattern';
$author = 'Imanda';
$id = 3;
$sql = "UPDATE books
SET title=?, author=?
WHERE id=?";
$q = $conn->prepare($sql);
$q->execute(array($title,$author,$id));
From what I can see, method two does not bind the data, rather insert it directly into the query as an array type. Does this make the script more susceptible to SQL injection or other security risks?
The only difference between the two is that if you pass the array in to the execute function rather than calling bindParam yourself, it treats all parameters as PDO::PARAM_STR automatically, whereas in calling bindParam yourself you could bind them as integers, etc.
From the docs:
input_parameters
An array of values with as many elements as there are bound parameters in the SQL statement being executed. All values are treated as PDO::PARAM_STR.
You can also see from the examples there that you can use named parameters (e.g. :limit) when passing the array into the execute function. You don't have to just put ?. In that case you give the array a key:
$sth->execute(array(':calories' => $calories, ':colour' => $colour));
It's mostly a matter of preference. Both protect you from injection.
Though I think it's much easier to force data type with bind(), where as using execute(array()) will be using strings.

Using PHP functions in MySQL PDO

Can I use my own functions from PHP directly in SQL queries (using mySQL and PDO)? For example:
$query = null;
$result = null;
$query = $this->database_0->prepare("SELECT `id`, `salt` FROM `general_users` WHERE `username` = :username AND `password` = CONCAT(generatePassword(:password, `salt`)) LIMIT 1");
$query->bindValue(':username', $this->input->getValue('username'), PDO::PARAM_STR);
$query->bindValue(':password', $this->input->getValue('password'), PDO::PARAM_STR);
$query->execute();
$result = $query->fetch(PDO::FETCH_ASSOC);
$query->closeCursor();
Look at line 3 in "WHERE" case.
If it is not possible, I must use two queries just for check if a user exists, it do not look very optimal.
Thanks for your help, Bartek.
Can I use my own functions from PHP directly in SQL queries
No.
Mysql knows nothing of PHP and its functions. You are bound to use mysql functions in mysql and PHP functions in PHP. Quite easy to memorize.
So, here you go, with one single query
$sql = "SELECT id, salt, password FROM general_users WHERE username = ?";
$stmt = $this->db->prepare($sql);
$query->execute([$this->input->getValue('username')]);
$row = $query->fetch();
if (generatePassword($row['password'], $row['salt']) == $this->input->getValue('password'))
{
You can't use a PHP function in a MySQL query.
You can still do this with a single query. Just retrieve user info (including password) by comparing only its username. Then, in PHP, compare stored password with the one you have just computed. That would even allow you to distinguish two cases: "user exists, but password is wrong" and "user does not exist".

Categories