CREATE USER fails with Mysqli prepared statements - php

I'm trying to create a simple PHP script to create and assign attributes to an SQL user. The query works fine if no parameters are used, but fails otherwise.
Works fine
$conn = new mysqli('127.0.0.1', 'root', 'pass');
$sql = "CREATE USER 'newuser'#'localhost' IDENTIFIED BY 'password'";
$stmt = $conn->prepare($sql);
$stmt->execute();
Both username and password are ?
$conn = new mysqli('127.0.0.1', 'root', 'pass');
$sql = "CREATE USER '?'#'localhost' IDENTIFIED BY '?'";
$stmt = $conn->prepare($sql);
$uname = "carn";
$pass = "pass";
$stmt->bind_param('ss', $uname, $pass);
$stmt->execute();
Both username and password are ?
$conn = new mysqli('127.0.0.1', 'root', 'pass');
$sql = 'CREATE USER "?"#"localhost" IDENTIFIED BY "?"';
$stmt = $conn->prepare($sql);
$uname = "carn";
$pass = "pass";
$stmt->bind_param('ss', $uname, $pass);
$stmt->execute();
Error in syntax, check documentation
$conn = new mysqli('127.0.0.1', 'root', 'pass');
$sql = "CREATE USER ?#'localhost' IDENTIFIED BY ?";
$stmt = $conn->prepare($sql);
$uname = "carn";
$pass = "pass";
$stmt->bind_param('ss', $uname, $pass);
$stmt->execute();
Error in syntax, check documentation
$conn = new mysqli('127.0.0.1', 'root', 'pass');
$sql = "CREATE USER `?`#'localhost' IDENTIFIED BY `?`";
$stmt = $conn->prepare($sql);
$uname = "carn";
$pass = "pass";
$stmt->bind_param('ss', $uname, $pass);
$stmt->execute();
I'm not sure where to go from here. This might be an issue with the way I'm using quotes I saw two related questions here on SO but none of them answered properly.

With prepared statement you can use only limited subset of queries. Create user not included.
You can try INSERT into mysql.user table, something like
INSERT INTO `mysql`.`user` (Host,User,Password)VALUES(?,?,password(?));
Besides, with users created dynamically you are doing something wrong

Don't put single quotes around the ?, bind_param() will take care of it.
However, there is another issue that you can't use placeholders for CREATE USER statements in MySQL.
See How to write "create user ?" with MySQL prepared statement for a way of doing it.

Related

MySQL PDO: Invalid parameter number: parameter was not defined

I'm building a login page where the username can be that of either a student or teacher, where student names are simply numeric (i.e. 45678). I've made a function account_type($user) which just returns "student" if $user is numeric, and "teacher" if otherwise.
Edit: To clarify, students will type in their SID (i.e. 12345) to log in, and so my function account_type() will determine them to be a student. As such, the MySQL query to access a student account is different than the one to access a teacher's account, wherein an email address is required.
The student log in works fine with the named parameters, but when I try using a string and looking for an email, I get the error:
Invalid parameter number: parameter was not defined
I've tried putting quotes around the :user in the query, but that didn't help. I've triple checked that the queries are right, and they work on MySQL. Any ideas what I should do? The obvious answer is to use mysqli or to not use named parameters, but I'm hoping for it to work with named parameters for more complex queries later on.
Here's my code:
try {
$pdo = new PDO($dsn, DB_USERNAME, DB_PASSWORD);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}
catch (PDOException $e) {
die("Could not connect to database. " . $e->getMessage());
}
$user = mysqli_real_escape_string($link, $_POST['user']);
$pass = mysqli_real_escape_string($link, $_POST['pass']);
$account_Type = account_type($user);
if ($account_Type == "student") {
$query = "SELECT id, password FROM students WHERE sid = :user";
}
else if ($account_Type == "teacher") {
$query = "SELECT id, password FROM staff WHERE email = :user";
}
$stmt = $pdo->prepare($query);
$stmt->execute([
':user' => $user
]);
Thanks in advance!
There are two functions:
mysqli_real_escape_string which is supported in PHP 5 and 7 and must be used with mysqli: http://php.net/manual/en/mysqli.real-escape-string.php
And mysql_real_escape_string which was deprecated in PHP 5.5.0, and it was removed in PHP 7.0.0 and you can use withou a mysqli connection: http://php.net/manual/en/function.mysql-real-escape-string.php
In the comments of your question you posted a link that uses the mysql_real_escape_string but in your code you are using the mysqli_real_escape_string
So if you are using < PHP 7 or early you can use mysql_real_escape_string to improve your security without mysqli, like this:
$user = mysql_real_escape_string($_POST['user']);
but if you are using > PHP 7 then you must use mysqli, like in the example below:
<?php
//create a connection
$mysqli = new mysqli("localhost", "root", "", "school");
if (mysqli_connect_errno()) {
printf("Connect failed: %s\n", mysqli_connect_error());
exit();
}
//mysqli_real_escape_string is the procedural version of the function below
$user = $mysqli->real_escape_string('1');
$pass = $mysqli->real_escape_string('student1');
//verify if is a student or teacher
$is_student = is_numeric($user);
if ($is_student == true) {
$query = "SELECT sid, name, password FROM students WHERE sid =? AND password =?";
}
else {
$query = "SELECT sid, name, password FROM staff WHERE email =? AND password =?";
}
if ($stmt = $mysqli->prepare($query)) {
if($is_student){
//i for integer and s for string
$stmt->bind_param("is", $user, $pass);
}else{
//s for string and s for string
$stmt->bind_param("ss", $user, $pass );
}
$stmt->execute();
$stmt->bind_result($sid, $name, $password);
$stmt->fetch();
printf("sid: %s; name: %s; password: %s\n", $sid, $name, $password);
$stmt->close();
}
Hope this helps.

Prepared Statements Select with Variables - php

Trying to just set up something to verify that username = password via num_rows = 1.
Trying to use prepared statements, that I have never used before and i'm missing something. Where does the var in bind_results('s',$variable) come from??
Also, its just not working for me.
<?php
require ($_SERVER['DOCUMENT_ROOT'].'/db-connect.php');
$conn = new mysqli($servername, $username, $password, $dbname);
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}
$user = $_POST['username'];
//$user = $mysqli->real_escape_string($user);//
$password = $_POST['password'];
//$password = $mysqli->real_escape_string($password);//
if ($stmt = $mysqli->prepare("SELECT * FROM users WHERE username = ? AND password = ?")) {
$stmt->bind_result('ss', $username);
$stmt->execute();
$result = $stmt->num_rows;
echo $result;
$stmt->close();
}
$mysqli->close();
?>
I see three problems with this:
$stmt->bind_result('ss', $username);
First, bind_result PHP documentation:
"Binds columns in the result set to variables."
I think you're looking for bind_param. PHP documentation:
"Bind variables for the parameter markers in the SQL statement that was passed to mysqli_prepare()."
Second, your statement has two parameter markers (?), your bind statement indicates two strings (ss), but you provide only one variable ($username).
Third, $username is not what you're getting from $_POST['username']. You've assigned that to $user. $username is for your database connection.
I think it should work for you with this line instead:
$stmt->bind_param('ss', $user, $password);

Select 2 columns with PHP PDO Query

I'm pretty new to PHP and PDO and I'm trying to make a simple login system. Now, I'm trying to fetch the id and password from my table to compare with the password that the user input(I'm using one way encryption with salt). So, now the problem is, when I do $password = $stmt->fetchColumn(1) only, my login system works. Now when I try to get the id by doing $id = $stmt->fetchColumn(0) just before $password, I cannot login anymore and I get my "Wrong Username/Password" error.
Now I'm pretty sure that I'm doing something wrong with the fetchColumn but I can't figure it out.
Here's a code snippet that works:
$con = new PDO( DB_DSN, DB_USERNAME, DB_PASSWORD );
//set how pdo will handle errors
$con->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
//this would be our query.
$sql = "SELECT id, password FROM user_admin WHERE email = :email";
//prepare the statements
$stmt = $con->prepare( $sql );
//give value to named parameter :email
$stmt->bindValue( "email", $this->email, PDO::PARAM_STR );
$stmt->execute();
$password = $stmt->fetchColumn(1);
Now the following doesn't work. Notice that this happens when I added the $id:
$con = new PDO( DB_DSN, DB_USERNAME, DB_PASSWORD );
//set how pdo will handle errors
$con->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
//this would be our query.
$sql = "SELECT id, password FROM user_admin WHERE email = :email";
//prepare the statements
$stmt = $con->prepare( $sql );
//give value to named parameter :email
$stmt->bindValue( "email", $this->email, PDO::PARAM_STR );
$stmt->execute();
$id = $stmt->fetchColumn(0); //That's the problem
$password = $stmt->fetchColumn(1);
Any help is greatly appreciated.
From the documentation:
PDOStatement::fetchColumn — Returns a single column from the next row of a result set
Each time you call fetchColumn it advances to the next row of the result set.
Try using PDOStatement::fetch instead to fetch the entire row as an an array and then accessing the values from there.
$stmt->execute();
$row = $stmt->fetch();
$id = $row[0];
$password = $row[1];

PHP Prepare statement error

Fatal error: Call to a member function prepare() on a non-object in
/home/melazabi/public_html/assigment/The/include/process.php on line
15
// check if the username exists in the database
// line 15 is the one below:
$statement = $conn->prepare("select * from users where username=? AND password=?");
//prepare statment is to try to stop sql injection
$statement->bindParam(1, $un);
$statement->bindParam (2, $pw);
$statement->execute();
As per what you shown in your comment:
You're using a mysql_* based connection
$conn = mysql_connect('localhost','admin','admin') or die("error2"); mysql_select_db("admin") or die("error");
with a PDO query.
You need to use: (replace with actual DB credentials)
$dbname = 'admin';
$username = 'admin';
$password = 'admin';
$conn = new PDO("mysql:host=localhost;dbname=$dbname", $username, $password);
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
The error is telling you the your query failed for any number of reasons.
Your db connection failed, either authentication problem or complete failure to connect.
Your params are not defined correctly.
you can debug this by
print_r($statement->errorInfo());
this will give you what the error returned by sql was.
also make user variables are set. If i were to guess not having seen the rest of your code. you probably want $_POST['un'] and $_POST['pw']
echo $un;
echo $pw;
edit
connect to db:
$conn = new PDO('mysql:host='SERVERADDRESS';dbname=DBNAME;charset=utf8', 'USERNAME', 'PASSWORD');
then your query
$statement = $conn->prepare("select * from users where username=? AND password=?");
//prepare statment is to try to stop sql injection
$statement->bindParam(1, $un);
$statement->bindParam (2, $pw);
$statement->execute();

PHP PDO UPDATE not updating data

I am having a tough time updating data using PDO. These are the two options that i've tried. None has actually updated the database, however.
Query 1:
$dateLastLoggedIn = date("Y-m-d H:i:s");
$username = mysql_real_escape_string($_POST['User']);
$sth = $dbh->prepare("UPDATE users SET dateLastLoggedIn = ? WHERE username = ?");
$sth->execute(array($dateLastLoggedIn,$username));
print_r($sth->queryString); just prints out UPDATE users SET dateLastLoggedIn = ? WHERE username = ?
Query 2:
$dateLastLoggedIn = date("Y-m-d H:i:s");
$username = mysql_real_escape_string($_POST['User']);
$sql = "UPDATE users SET dateLastLoggedIn = '".$dateLastLoggedIn."' WHERE username = '".$username."'";
$sth = $dbh->prepare($sql);
$sth->execute();
print_r($sth->queryString); prints out UPDATE users SET dateLastLoggedIn = '2012-08-03 13:36:32' WHERE username = 'testuser'
The second option generates the correct query but it doesn't actually update the data. I can manually run the generated script and it works, but not through the execute(). Anything i'm doing wrong? I'm still new to PDO, so it may be a simple fix.
SOLVED: see my last comment under the accepted answer.
getting connection :
function getConnection(){
$dbhost="127.0.0.1";
$dbuser="application";
$dbpass="password";
$dbname="abc";
$dbh = new PDO("mysql:host=$dbhost;dbname=$dbname", $dbuser, $dbpass);
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}
try {
$dbh = getConnection();
$sth = $dbh->prepare("UPDATE users SET dateLastLoggedIn = :dateLastLoggedIn WHERE username = :username ");
$sth->bindParam('dateLastLoggedIn',$dateLastLoggedIn);
$sth->bindParam('username',$username );
$sth->execute();
$dbh = null; // after done
} catch(PDOException $e) {// simple exception handling
error_log($e->getMessage(), 3, '/var/tmp/php.log');
echo '{"error":{"text":'. $e->getMessage() .'}}';
}
Also, try to wrap this in try catch to see the error
print_r($sth->queryString); just prints out UPDATE users SET dateLastLoggedIn = ? WHERE username = ?
That's what will happen with PDO prepared queries.
If you're using PDO, mysql_real_escape_string isn't going to work. At all. It requires an existing connection via mysql_connect. Your username value is effectively blank.

Categories