Pourquoi PDO est-il meilleur pour échapper aux requêtes MySQL/querystrings que mysql real escape string?

on m'a dit que je préférerais utiliser PDO pour échapper à MySQL, plutôt que mysql_real_escape_string .

peut - être que j'ai une journée de mort cérébrale (ou c'est peut-être le fait que je ne suis pas du tout un programmeur naturel, et je suis encore très au stade de débutant quand il s'agit de PHP), mais après avoir vérifié le manuel PHP et avoir lu l'entrée sur PDO , Je ne suis toujours pas plus clair quant à ce que PDO est réellement et pourquoi il est mieux que d'utiliser mysql_real_escape_string . C'est peut-être parce que je n'ai pas encore vraiment eu à faire face aux complexités de L'OOP (je suppose que c'est quelque chose à voir avec L'OOP), mais mis à part le fait que les variables et les valeurs de tableau semblent avoir un avant-goût d'eux, je ne suis pas encore sûr de ce qu'il est réellement et comment vous l'utilisez (et pourquoi il est mieux que mysql_real_escape_string . (Cela peut aussi avoir quelque chose à voir avec le fait que je n'ai pas vraiment une compréhension claire de ce que sont les "classes", donc quand je lis "classe AOP" Je ne suis pas le plus sage vraiment.)

ayant lu un article ou deux sur le morceau" Developer Zone " du site MySQL, Je ne suis pas encore plus clair. Comme je n'arrive même pas à comprendre ce que c'est pour le moment, je pense que probablement l'utiliser me dépasse un peu en ce moment, mais je suis toujours intéressé à élargir mon éducation et à découvrir comment je pourrais améliorer les choses.

est-ce que quelqu'un pourrait m'expliquer en "anglais simple" ce QU'est une AOP (ou me pointer dans la direction de quelque chose sur le sujet écrit en anglais), et comment vous feriez pour l'utiliser?

48
demandé sur BlissC 2009-11-16 16:01:12

6 réponses

comme les réponses actuelles vont dans les détails alors que votre question est plus axée sur un aperçu général, je vais lui donner un essai:

les classes PDO visent à encapsuler toutes les fonctionnalités nécessaires pour interagir avec une base de données. Ils le font en définissant les "méthodes" (oo parlor pour les fonctions) et les "propriétés" (OO parlor pour les variables). Vous les utilisez comme un remplacement complet pour toutes les fonctions "standard" que vous utilisez maintenant pour parler à un la base de données.

ainsi, au lieu d'appeler une série de fonctions 'mysql_doSomething ()', en stockant leurs résultats dans vos propres variables, vous "instanciez" un objet de la classe PDO ('class' = abstract definition, 'object' = concrete, usable instance of a class) et appelez les méthodes sur cet objet pour faire de même.

par exemple, sans AOP, vous feriez quelque chose comme ça:

// Get a db connection
$connection = mysql_connect('someHost/someDB', 'userName', 'password');
// Prepare a query
$query = "SELECT * FROM someTable WHERE something = " . mysql_real_escape_string($comparison) . "'";
// Issue a query
$db_result = mysql_query($query);
// Fetch the results
$results = array();
while ($row = mysql_fetch_array($db_result)) {
  $results[] = $row;
}

alors que ce serait l'équivalent utilisation de L'AOP:

// Instantiate new PDO object (will create connection on the fly)
$db = new PDO('mysql:dbname=someDB;host=someHost');
// Prepare a query (will escape on the fly)
$statement = $db->prepare('SELECT * FROM someTable WHERE something = :comparison');
// $statement is now a PDOStatement object, with its own methods to use it, e.g.
// execute the query, passing in the parameters to replace
$statement->execute(array(':comparison' => $comparison));
// fetch results as array
$results = $statement->fetchAll();

donc à première vue, il n'y a pas beaucoup de différence, sauf en syntaxe. Mais la version AOP présente certains avantages, le plus important étant l'indépendance de la base de données:

si vous avez besoin de parler à une base de données PostgreSQL à la place, vous changerez seulement mysql: en pgsql: dans l'appel instanciation new PDO() . Avec l'ancienne méthode, vous devez passer en revue tout votre code, en remplaçant toutes les fonctions' mysql_doSomething () ' par leurs 'pg_doSomthing ()' counterpart (toujours en vérifiant les différences potentielles dans la manipulation des paramètres). Le même se serait le cas pour de nombreux autres moteurs de base de données.

donc pour revenir à votre question, AOP fondamentalement vous donne juste une manière différente de réaliser les mêmes choses, tout en offrant quelques raccourcis/améliorations/avantages. Par exemple, l'évasion se produirait automatiquement de la manière appropriée nécessaire pour le moteur de base de données que vous utilisez. Aussi substitution de paramètre (empêche les Injections de SQL, pas montré en exemple) est beaucoup plus facile, ce qui le rend moins sujet à l'erreur.

Vous devriez lire sur certaines bases de la POO pour avoir une idée de d'autres avantages.

57
répondu Henrik Opel 2012-04-10 15:57:17

Je ne suis pas très familier avec PDO, mais il y a une distinction entre "déclarations préparées" et cordes échappées. Échapper est d'environ supprimer les chaînes de caractères non autorisées de la requête, mais les déclarations préparées sont d'environ dire à la base de données quel type de requête à attendre .

Une requête comporte plusieurs parties

Pensez-y de cette façon: lorsque vous faites une requête à la base de données, vous êtes dire plusieurs choses distinctes. Une chose peut être, par exemple, "je veux vous faire une sélection."Another might be" limite cela aux lignes où le nom d'utilisateur est la valeur suivante."

si vous compilez une requête sous forme de chaîne de caractères et que vous la Donnez à la base de données, elle ne connaît aucune des deux parties jusqu'à ce qu'elle obtienne la chaîne complète. Vous pourriez faire ceci:

'SELECT * FROM transactions WHERE username=$username'

Quand il fait cette chaîne, il doit analyser et décider "c'est un SELECT avec un WHERE ".

obtenir les pièces mélangées

supposons qu'un utilisateur malveillant entre son nom d'utilisateur comme billysmith OR 1=1 . Si vous n'êtes pas prudent, vous pourriez mettre cela dans votre chaîne, résultant en:

'SELECT * FROM transactions WHERE username=billysmith OR 1=1'

...qui retournerait toutes les transactions pour tous les utilisateurs , parce que 1 égale toujours 1. Oups, vous avez été piraté!

vous voyez ce qui s'est passé? le la base de données ne savait pas à quoi s'attendre dans votre requête , donc elle a juste analysé la chaîne de caractères. Il n'a pas été surpris que le WHERE ait un OR , avec deux conditions qui pourraient le satisfaire.

garder les parties droites

si seulement il avait su à quoi s'attendre , à savoir, un SELECT dont WHERE avait une seule condition, l'utilisateur malveillant ne pouvait pas l'avoir trompé.

avec une déclaration préparée, vous pouvez lui donner cette attente correcte. Vous pouvez dire à la base de données "je suis sur le point de vous envoyer un SELECT , et il va être limité aux lignes WHERE username = une chaîne que je suis sur le point de vous donner. C'est tout - il n'y a pas d'autres parties à la requête. Êtes-vous prêt? OK, voici la chaîne à comparer au nom d'utilisateur."

avec cette attente, la base de données ne serait pas dupe: elle retournerait seulement les lignes où le username la colonne contient la chaîne de caractères 'billysmith ou 1 = 1."Si personne n'a ce nom d'utilisateur, il ne retournera rien.

autres avantages des déclarations préparées

en plus des avantages de sécurité, déclarations préparées ont un couple d'avantages de vitesse:

  • ils peuvent être réutilisés avec des paramètres différents, ce qui devrait être plus rapide que la construction d'une nouvelle requête à partir de zéro, parce que la base de données sait déjà vous êtes sur le point de demander. Il a déjà construit son "plan de requête".
  • certaines bases de données (Postgres en est une, je pense) vont commencer à faire un plan de requête dès qu'ils reçoivent la déclaration préparée - avant que vous avez réellement envoyé les paramètres à utiliser avec elle. Donc vous pouvez voir une accélération même sur la première requête.

pour une autre explication, voir la réponse de Theo ici .

39
répondu Nathan Long 2017-05-23 12:34:00

contrairement à mysql_real_escape_string, PDO vous permet d'appliquer un type de données.

<?php
/* Execute a prepared statement by binding PHP variables */
$calories = 150;
$colour = 'red';
$sth = $dbh->prepare('SELECT name, colour, calories
    FROM fruit
    WHERE calories < :calories AND colour = :colour');
$sth->bindParam(':calories', $calories, PDO::PARAM_INT);
$sth->bindParam(':colour', $colour, PDO::PARAM_STR, 12);
$sth->execute();
?>

notez que dans l'exemple ci-dessus, le premier paramètre, calories, doit être un entier (PDO::PARAM_INT).

Deuxièmement, pour moi, les requêtes AOP paramétrées sont plus faciles à lire. Je préfère lire:

SELECT name FROM user WHERE id = ? AND admin = ? 

que

SELECT name FROM user WHERE id = mysql_real_escape_string($id) AND admin = mysql_real_escape_string($admin);

Troisièmement, vous ne devez pas vous assurer de citer les paramètres correctement. AOP prend soin de cela. Par exemple, mysql_real_query_string:

SELECT * FROM user WHERE name = 'mysql_real_escape_string($name)' //note quotes around param

vs

SELECT * FROM user WHERE name = ?

enfin, PDO vous permet de porter votre application à un db différent sans changer vos appels de données PHP.

16
répondu Cory House 2011-02-18 17:16:01

imaginez que vous écrivez quelque chose comme:

$query = 'SELECT * FROM table WHERE id = ' . mysql_real_escape_string($id);

cela ne vous sauvera pas d'injections, parce que $id pourrait être 1 OR 1=1 et vous obtiendrez tous les enregistrements de la table. vous devez lancer $id au bon type de données (int dans ce cas)

pdo a un autre avantage, et c'est l'interchangeabilité des bases de données backends.

14
répondu knittl 2009-11-16 13:15:01

en plus d'empêcher L'injection SQL, PDO vous permet de préparer une requête une fois et de l'exécuter plusieurs fois. Si votre requête est exécutée plusieurs fois (dans une boucle, par exemple), cette méthode devrait être plus efficace (je dis "devrait", car il semble que ce n'est pas toujours le cas sur les anciennes versions de MySQL). La méthode prepare/bind est également plus conforme aux autres langues avec lesquelles j'ai travaillé.

3
répondu Wes 2009-11-16 13:25:23

pourquoi PDO est-il meilleur pour échapper aux requêtes MySQL/querystrings que mysql_real_escape_string?

simplement parce que "s'échapper" seul n'a aucun sens.

De plus, il est différent questions incomparables .

le seul problème avec l'évasion est que tout le monde se trompe, le supposant comme une sorte de"protection".

Tout le monde dit "j'ai échappé à mes variables" avec la signification "j'ai protégé ma requête".

Alors que s'échapper seul n'a rien à voir avec la protection du tout.

la Protection peut être obtenue en gros dans le cas de j'ai échappé et cité mes données , mais il n'est pas applicable partout, pour les identificateurs par exemple (ainsi que AOP, soit dit en passant).

donc, la réponse est:

  • PDO, en faisant échapper pour les valeurs liées, s'applique non seulement échapper, mais aussi citer - c'est pourquoi il est préférable.
  • "s'échapper" n'est pas synonyme de "protection". "échapper + citer" est en gros.
  • mais pour certaines parties de requête les deux méthodes sont inapplicables.
3
répondu Your Common Sense 2012-04-12 13:29:48