I've learned PHP from a book and its told me to use PDO objects or sql statements (I'm not sure if that's the right terminology, I apologize if it's not).
When I look up sql stuff, a lot of the times I see stuff like this:
$link = mysql_connect('localhost', 'mysql_user', 'mysql_password');
if (!$link) {
die('Could not connect: ' . mysql_error());
}
if (!mysql_select_db('database_name')) {
die('Could not select database: ' . mysql_error());
}
$result = mysql_query('SELECT name FROM work.employee');
But in my code and in the book, I'm doing stuff like this:
global $db;
$query = "SELECT * FROM users WHERE username='$username'";
$results = $db->query($query);
$results = $results->fetch();
What's the difference between these two 'styles'?
First the function those are mysql_* (like mysql_query, mysql_connect etc) are deprecated and will not be supported in PHP future versions. So PDO or Mysqli are preferred way of communication with database.
The PDO 's prepared statements are used for avoiding SQL injection attacks. like in normal mysql_query you will use like this
$query = "SELECT * FROM users WHERE username='$username'";
$results = mysql_query($query);
but in PDO you have to use like this
$params = array(':username' => 'test', ':email' => $mail);
$pdo->prepare('
SELECT * FROM users
WHERE username = :username
AND email = :email');
$pdo->execute($params);
So PDO is recommended way. For more detail you can refer to
http://wiki.hashphp.org/PDO_Tutorial_for_MySQL_Developers
http://php.net/pdo
http://net.tutsplus.com/tutorials/php/why-you-should-be-using-phps-pdo-for-database-access/
The first style was written long ago, or was written by people who stopped learning PHP before PHP5 came out. mysql_query is deprecated, and has been for a while now, and you should never be using it in a new project.
The second is using PDO, one of the newer database APIs. PDO supports a bunch of things that make working with SQL easier.
It's still pretty hideous as written, though. Most people would recommend using parameterized queries (a form of prepared statements) to separate the data from the SQL. This helps prevent "SQL injection", a process by which someone feeds you data that tricks your database into executing queries you never intended for it to.
Related
I can't figure out why my SQL select query keeps failing - I am new to SQL so it might b a stupid mistake but I have not been able to find the answer in the documentation. Thanks a lot in advance
// connect to db
$mysqli = new mysqli("127.0.0.1", "maok08ab", "", "Portfolio");
if ($mysqli->connect_errno)
{
echo "Failed to connect to MySQL";
}
$username=$_POST["username"];
$email=$_POST["email"];
$hash=$_POST["password"];
$query = "SELECT * FROM users WHERE username = '$username'";
$result= mysqli_query($mysqli, $query);
if ($result == FALSE)
{
apologize("something went wrong");
}
Since you're using an OOP connection you have to use OOP to perform the query:
$query = "SELECT * FROM users WHERE username = '$username'";
$result = $mysqli->query($query);
It states very clearly in the manual:
Link Procedural style only: A link identifier returned by mysqli_connect() or mysqli_init()
So your use of $result= mysqli_query($mysqli, $query); will not work as you would think. Make sure to stick with one method (OOP or procedural) throughout the life of your code.
In addition:
Learn about prepared statements for MySQLi. Even escaping the string is not safe! Don't believe it?
Never store plain text passwords! Please use PHP's built-in functions to handle password security. If you're using a PHP version less than 5.5 you can use the password_hash() compatibility pack. Make sure you don't escape passwords or use any other cleansing mechanism on them before hashing. Doing so changes the password and causes unnecessary additional coding.
So I am trying to make some sort of page with stories for example
if(!empty($_GET['page']) && ctype_digit($_GET['page'])) {
$id = mysql_escape_string($_GET['page']); //in case ctype_digit didnt work well.
$pDatabase = Database::getInstance();
$query = "SELECT * FROM stories WHERE id = '$id'";
$result = $pDatabase->query($query) or die('Query failed: ' . mysql_error());
if(mysql_num_rows($result) >0){
//displaying current story
}
else {
header('Location: ' . $_SERVER['HTTP_REFERER']);
}
}
else {
//Show all short stories
}
I want to make sure it is completely safe using $_GET method and mysql query this way , if its not please tell what will be better in this case. Also another thing that bothers me is that I use the query all the time , is it right or should I have some function that would preread all database info before even site launched ? I Mean , what if I want to store Tags or site Title in the Database? Will it be wrong executing (mysql query) title and tags of every page within every page load?
You should not be using MySQL functions built in to PHP, because they are deprecated. Use MySQLi or PDO and learn about prepared statements. I will start by guiding you in the right direction. Trust me, it is worth your time to worry about this, because not using prepared statements could increase chances of SQL injection.
MySQLi - http://php.net/manual/en/intro.mysqli.php
More about prepared statements with MySQLi - http://www.php.net/manual/en/mysqli.quickstart.prepared-statements.php
PDO - http://www.php.net/manual/en/intro.pdo.php
More about prepared statements with PDO - http://www.php.net/manual/en/pdo.prepared-statements.php
I have a simple scenario: a user connects to "get.php?city=london", the server then searches the MySQL database for the data matching that request and outputs it.
I am using the following code to do this:
<?php
$con = mysql_connect( 'localhost', 'user', 'pass') or die('Could not connect to mysql server.' );
mysql_select_db('mydb', $con) or die('Could not select database.');
if(!isset($city)) return;
$c=$_GET["city"];
$q = "select * FROM cities WHERE city = '{$c}'";
$re = mysql_query($q);
... etc
Is it secure to simply insert the GET variable into the query like this? Will this make me vulnerable to a MySQL injection? Is there a more secure way to do this?
Regards
UPDATE:
would that be more secure?:
if(!isset($city)) return;
$city=$_GET["city"];
$q = "SELECT row1, row2 WHERE city= ?;";
$mysqli = new mysqli('localhost', 'root', 'pass', 'dbname');
$stmt = $mysqli->stmt_init();
if($stmt->prepare($q)){
$stmt->bind_param("s", mysql_real_escape_string($city));
$stmt->execute();
$stmt->bind_result($row1, $row2);
while ($stmt->fetch()) {
//do stuff with the data in the $row array
}
$stmt->close();
}
It's not secure at all, GET requests can be faked by simply changing the web address.
Trusting user input is dangerous. Someone could change the value of the city parameter, inject SQL into your query, and gain access to your data. You should be using prepared statements. That means that you need to use either the mysqli extension or the PDO extension.
I recommend using the PDO extension, mainly because it allows you to switch databases in the future without having to re-write all the code.
No they are not in mysql_* functions. You need to sensitize them using mysql_real_escape_string.
Better to use PDO with bindParams and the PDO library will do it for you.
php.net/pdo_mysql
http://in3.php.net/manual/en/pdostatement.bindparam.php
If you use mysql_real_escape_string user couldn't pass a string to mysql injection. On that purpose, for cities, I think there are not problem to use GET. However if you use personal user information I would use $_POST
hi im starting to use PDO for sqlite and I want to know how to do something similar like:
$result = **sqlite_query**($conection,$consulta);
for example something similar to $conection = sqlite_open('../db/traductor.db');
would be--->$conection = new PDO('sqlite:../db/traductor.db');
hope you can understand my question, and thanks
As you've been pointed, the PHP PDO manual page will tell you where to look for, but I'll save you a couple of minutes.
In procedural MySQL, you would connect to your database with:
$link = mysql_connect("localhost", "user", "password");
mysql_select_db("database", $link);
And fire your queries like:
$query = mysql_query("SELECT * FROM `products` ORDER BY `product_id` ASC;", $link);
In PDO, it's a bit different:
$pdo = new PDO("mysql:host=localhost;dbname=database;charset=utf8", "user", "password");
And you fire your queries (in a direct fashion) like this:
$pdo->query("SELECT * FROM `products` ORDER BY `product_id` ASC;");
But the power of PDO lies within prepared statements
$statement = $pdo->prepare("SELECT * FROM `products` WHERE `price` > ? ORDER BY `product_id` ASC;");
$statement->execute([27.75]);
Take your time and read the PDO manual page and as many tutorials on the web as you can. It's more difficult to work with PDO in the beginning but, once you learn, you won't want to work with anything less (not to mention you can link with MySQL, SQL Server, Oracle, PostgreSQL, MongoDB and many other databases using the same structure, among other advantages).
Hope that helped ;)
I have created my own mvc pattern based on the codeigniter framework style. My problem now is that i want to prevent from SQL injection, and for that purpose i would like to use mysql_real_escape_string(). But for when i use it, it keeps erroring since it apparently don't have a the "link/source" to the database?
I get the php error:
Warning: mysql_real_escape_string(): Can't connect to local MySQL
server through socket '/var/lib/mysql/mysql.sock' (2) in
/hsphere/local/home/../dev/simple_blog/models/users_model.php on line
8
Warning: mysql_real_escape_string(): A link to the server could not be
established in
/hsphere/local/home/../dev/simple_blog/models/users_model.php on line
8
I don't quite understand why though, since i can get stuff in and out of my DB but for some reason i can't protect it???
Here is my function giving the error
public function getUserByName($username){
$username = mysql_real_escape_string($username);
$sql = "SELECT * FROM ".$this->db_table." WHERE username='".$username."' LIMIT 1";
$q = $this->db->query($sql);
if($q->rowCount() > 0){
foreach($q->fetch() as $key => $row){
$data[$key] = $row;
}
return $data;
}
}
As you can see I use mysql_real_escape_string() at the top, and then later on, do query stuff. Anyone know why this don't work and if yes, how would i fix it?
NOTE: Im not a shark to PDO, and $this->db is the PDO class.
To use mysql_real_escape_string you'll need to connect to the database server first, using the MySQL Functions, which you probably don't have done.
You are mixing up two completely different PHP extensions: mysql and PDO!
Also, you don't need to escape strings, when using PDO prepared statements, that's done via PDO for you.
An example using PDO:
$userDataStmt = $this->database->prepare('SELECT * FROM ' . $this->db_table . ' WHERE username = :username LIMIT 1');
$userDataStmt->bindValue(':username', $username);
$userDataStmt->execute();
if(!$userDataStmt->rowCount() <= 0)
{
$result = $userDataStmt->fetchAll();
}
Don't do this. PDO will escape for you if you use prepared statements:
$stmt = $this->db->prepare("SELECT * FROM ".$this->db_table." WHERE username=:user LIMIT 1";
$stmt->bind(':user', $username);
$stmt->execute();
PDO uses (I believe) the mysqli library behind the scenes. mysql_escape_real_string uses the mysql library (note the lack of an i). Both libraries have completely independent connection pools, so unless you establish a throw-away link with mysql_connect(), you cannot use mysql_real_escape_string anyways, as it requires an active DB connection.
The PDO version is PDO::quote(). See http://php.net/manual/en/pdo.quote.php
So in your case it would be
$username = $this->db->quote($username);
However, most recommend using PDO prepared statements for avoiding SQL Injection in PDO. See
http://php.net/manual/en/pdo.prepared-statements.php