J'ai toujours fait la connexion simple de en utilisant cela, j'ai toujours utilisé le méthode simple pour échapper aux données avant de faire une requête, que ce soit maintenant je comprends que cela est sûr, dans une mesure! p> Il échappe aux caractères dangereux; Cependant, il est toujours vulnérable à d'autres attaques pouvant contenir des caractères sûrs, mais peut être nocive pour afficher des données ou dans certains cas, modifier ou supprimer des données malicieusement. P> Alors, j'ai cherché un peu et a découvert À propos de PDO, MySQLI et des déclarations préparées. Oui, je suis peut-être en retard au jeu, mais j'ai lu beaucoup, beaucoup de tutoriels (Tizag, W3C, blogs, Google Recherches) et pas un seul a mentionné cela. Il semble très étrange de savoir pourquoi, comme il suffit d'échapper à l'entrée de l'utilisateur n'est vraiment pas sécurisé et pas une bonne pratique pour le moins. Oui, je suis conscient que vous puissiez utiliser regex pour l'aborder, mais je suis toujours sûr que ça ne suffit pas? P> C'est à ma compréhension que l'utilisation de déclarations PDO / préparées est une façon beaucoup plus sûre de Stockez et récupérez des données d'une base de données lorsque les variables sont données par l'entrée de l'utilisateur. Le seul problème est que le commutateur sur (surtout après avoir été très bloqué dans mes habitudes / habitudes de codage précédent) est un peu difficile. P> Je comprends maintenant que de vous connecter à ma base de données à l'aide de PDO, j'utiliserais P> mysql_connect code>,
mysql_pconnect code>:
insérer code>,
Sélectionnez code>,
met à jour code> ou
Supprimer code> par Utilisation de
mysql_real_escapape_string code> p>
$username = $_POST['username'];
$email = $_POST['email'];
$stmt = $dbh->prepare("INSERT INTO `users` (username, email)
VALUES (:username, :email)");
$stmt->bindParam(':username, $username, PDO::PARAM_STR, ?_LENGTH_?);
$stmt->bindParam(':email, $email, PDO::PARAM_STR, ?_LENGTH_?);
$stmt->execute();
4 Réponses :
Je ne me préoccupe jamais avec BindParam () ou des types de paramètres ou de longueurs.
Je viens de passer une gamme de valeurs de paramètre pour exécuter (), comme ceci: p> Ceci est tout aussi efficace et plus facile à code. P> < P> Vous pouvez également être intéressé par ma présentation Mythes d'injection SQL et Fallacies , ou mon Réservez SQL AntiPatterns: Éviter les pièges de la programmation de la base de données . P> P>
Pourrait-il aussi être fait avec? Les espaces réservés dans le tableau alors? Dites Sélectionnez * à partir des utilisateurs où nom =? Et email =? "); Code> avec
exécuté (tableau $ (nom $, $ email)); code> ou cela ne fonctionne pas dans ce cas?
Oui, vous pouvez utiliser des paramètres de position au lieu de paramètres nommés, comme vous le souhaitez.
Pour répondre à la question de la longueur, spécifiez-le est facultatif, sauf si le paramètre de paramètre de paramètre est un paramètre OUT à partir d'une procédure stockée, donc dans la plupart des cas, vous pouvez l'omettre en toute sécurité.
En ce qui concerne la sécurité, l'échappement est terminé. dans les coulisses lorsque vous liez les paramètres. Cela est possible car vous avez dû créer une connexion de base de données lorsque vous avez créé l'objet. Vous êtes également protégé des attaques d'injection SQL depuis la préparation de la déclaration, vous indiquez à votre base de données au format de l'instruction avant que l'entrée de l'utilisateur ne puisse obtenir n'importe où. Un exemple: p> Ainsi, en termes de sécurité, vos exemples ci-dessus semblent bien. P> Enfin, je conviens que les paramètres de liaison individuellement sont fastidieux et sont Tout comme efficacement fait avec un tableau transmis à PDOStatement-> Exécuter () (voir http: //www.php.net/manual/fr/pdostatement.execute.php ). P> p>
Merci pour la question intéressante. Vous y allez:
Il échappe aux caractères dangereux, P> blockQuote>
Votre concept est tout à fait
faux. strong>
En fait, "personnages dangereux" est un mythe, il n'y en a pas. Et mysql_real_escape_string s'échappant mais simplement un délimiteurs de chaîne em>. À partir de cette définition, vous pouvez conclure ses limitations - cela ne fonctionne que pour Strings em>. P>Cependant, il est toujours vulnérable à d'autres attaques pouvant contenir des caractères sûrs, mais peut être nocif pour afficher des données ou dans certains cas, modifier ou supprimer des données malicieusement. P> BlockQuote>
Vous mélangez ici tout.
Parlant de base de données, P>
- pour les cordes, il est
pas vulnérable. strong> aussi longtemps que vos cordes citées et échappées, elles ne peuvent forts> "modifier ou supprimer des données malicieusement". * < / code> li>
- pour les autres données Typedata - Oui, c'est inutile em>. Mais pas parce que c'est un peu "dangereux" mais juste à cause d'une utilisation inappropriée. li> ul>
Quant aux données d'affichage, je suppose qu'il est offtopic fort> dans la question liée à la PDO, comme
PDO n'a rien à voir avec l'affichage des données non plus. strong> < / p> Échapper l'entrée utilisateur p> blockQuote>
^^^ Une autre illusion à noter! p>
Une entrée d'utilisateur n'a absolument rien à voir avec une échappée forte>. Comme vous pouvez apprendre de la définition antérieure, vous devez échapper aux chaînes, pas n'importe quelle "entrée utilisateur". Donc, encore une fois: p>
- Vous avez des cordes d'évasion, quelle que soit leur source li>
- Il est inutile d'échapper à d'autres types de données, quelle que soit la source. LI> ul> li> ul>
a eu le point?
Maintenant, j'espère que vous comprenez les limites de l'échappement ainsi que de la fausse idée des "personnages dangereux". P>C'est à ma compréhension que l'utilisation de déclarations de PDO / préparées est une p> beaucoup plus sûre blockQuote>
pas vraiment.
En fait, il existequatre forts> différentes parties de requête que nous pouvons y ajouter de manière dynamique: p>
- une chaîne li>
- un nombre li>
- un identifiant li>
- Un mot clé de syntaxe. li> ul>
Ainsi, vous pouvez voir que l'échappement ne couvre qu'un seul problème. (Mais bien sûr, si vous traitez des chiffres en tant que chaînes (les mettre dans des guillemets), le cas échéant, vous pouvez les faire en sécurité) P>
tandis que des déclarations préparées - UGH - Entier 2 Isues! Une grosse affaire; -) p>
pour les 2 autres numéros Voir ma réponse précédente, Dans PHP Lors de la soumission des chaînes à la base de données Devrais-je m'occuper de caractères illégaux à l'aide de HTMLSpecialchars () ou d'utiliser une expression régulière? p>
MAINTENANT, les noms de fonction sont différents, donc ne plus mon mysql_query, mysql_fetch_array, mysql_num_rows, etc. p> blockquote>
c'est une autre,
grave illusion de php utilisateurs em>, strong> une catastrophe naturelle, une catastrophe: p> même lorsqu'il utilise Old MySQL Driver, On ne devrait jamais utiliser les fonctions d'API nues forte> dans leur code! Il faut les mettre dans une fonction de bibliothèque pour l'utilisation quotidienne! (Pas comme un rite magique, mais simplement pour rendre le code plus court, moins répétitif, une épreuve d'erreur, plus cohérente et lisible). P>
la même chose va aussi pour le PDO! STRUT > p> maintenant sur votre question à nouveau. P>
mais en les utilisant, cela élimine la nécessité d'utiliser quelque chose comme mysql_real_escapape_string? P> blockQuote>
oui. p>
Mais je pense que c'est à peu près l'idée de ce qui devrait être fait pour récupérer un utilisateur d'une base de données p> blockQuote>
ne pas récupérer, mais pour ajouter une donnée à la requête em>! p>
Vous devez donner une longueur après PDO: Param_str si je ne me trompe pas p> BlockQuote>
Vous pouvez, mais vous n'êtes pas obligé. P>
Maintenant, est-ce tout sûr? P> BlockQuote>
En termes de sécurité de la base de données, il n'y a pas de points faibles dans ce code. Rien à sécuriser ici. p>
pour l'affichage de la sécurité - il suffit de rechercher ce site pour le mot clé code> xss code>. p>
J'espère que je vis une lumière sur la matière. P>
BTW, pour les inserts longs, vous pouvez utiliser la fonction que j'ai écrit un jour, Insérer / mettre à jour la fonction d'assistance à l'aide de PDO P>
Cependant, je n'utilise pas de déclarations préparées pour le moment, car je préfère mes espaces réservés à domicile sur eux, en utilisant une bibliothèque em> j'ai mentionné ci-dessus. Donc, pour contrer le code posté par le RIHA ci-dessous, il serait aussi court que ces 2 lignes: p>
xxx pré> mais bien sûr, vous pouvez avoir le même code à l'aide de déclarations préparées bien. P>
* (Oui, je suis au courant des contes de peur de Schiflett) Code> P> P>
Merci :) maintenant, je suppose. Je marque généralement la question elle-même, si je veux le signet
Pourquoi encourager l'OP à utiliser une bibliothèque auto-codée lorsque l'OP demande réellement comment utiliser correctement PDO? La première étape vient en premier, vous savez? Une recrue (qui vient d'apprendre qu'il y a plus que mysql_ *) devrait vraiment apprendre l'utilisation de la PDO de base avant même d'envisager une bibliothèque d'emballage DB personnalisée. En outre, deux doublures comme la vôtre sont un pita pour lire / comprendre / déboguer / modifier / modifier. Le code court n'est pas toujours le meilleur code.
Eh bien, bien que ce soit un peu bon, je suis sûr qu'il devrait y avoir un avertissement de toute façon, juste pour montrer la voie à suivre. Et, pour défendre mon 2 doublure, j'oserais dire que c'est bien plus amical de débogage que votre 7-doublure, il est lisible et facile à modifier. Si vous pouvez me montrer certains points faibles de ce code particulier, pas en 2-doublures en général, je l'apprécierai cependant.
@ Col.shrapnel - une fois de plus, vous avez répondu avec une réponse vraiment détaillée et constructive! Tout le monde a! J'avais certainement une meilleure compréhension de tout ce qui est de toute façon, je vais essayer les méthodes de votre et de RIHA et de voir ce que je me sens à l'aise jusqu'à ce que je comprenne plus de compréhension de tout cela. Merci!
@ Col.shrapnel Je trouve le code plus difficile à lire et à modifier, mais c'est probablement la préférence personnelle. Cependant, il ne joue pas bien avec les VC comme Git / Mercurial. Imaginez que vous devez ajouter une nouvelle ligne à la condition d'une branche de fonctionnalité. Ensuite, il y a un autre changement sur une autre branche. Maintenant, les deux branches de fonctionnalités doivent être fusionnées à la branche principale - Conflit de fusion! Amusez-vous à résoudre les mois après que vous l'avez codé et que vous avez oublié longtemps ce que le code est à propos. Avec cela à l'esprit, le code de grammage ensemble sur peu de lignes est presque toujours hors de question. Ça va te mordre quand on s'attendrale au moins. :)
@riha parlez-vous de la requête elle-même? Faites-vous ce que vous le souhaitez, le point de mon code est complet différent b>. Je suis désolé que tu ne l'as pas eu.
Le point de votre code est de laisser votre bibliothèque gérer la préparation de la requête et des liaisons de paramètres. Quoi qu'il en soit, arrêtons de violer les commentaires.
@riha, il n'automise pas seulement ces liaisons répétées inutiles. Il interroge également l'exécution, la manipulation des erreurs, la récupération de données, le profilage, la journalisation de la requête, la manipulation de la connexion et plus encore. allez comprendre.
Oui,: Quelque chose est un espace réservé nommé en PDO ,? est un espace réservé anonyme. Ils vous permettent de se lier les valeurs un à une ou une fois à la fois.
Ainsi, fondamentalement, cela fait quatre options pour fournir votre requête avec des valeurs. P>
Ceci lie une valeur concrète à votre espace réservé dès que vous l'appelez. Vous pouvez même lier des chaînes codées dures telles que Fournir un type de paramètre est facultatif (mais suggéré). Cependant, puisque la valeur par défaut est Je préfère habituellement cette approche. Je trouve le plus propre et le plus flexible. Em> p> une variable est liée à votre espace réservé qui sera lu lorsque la requête est Bindvalue (': quelque chose', 'foo') code> si vous le souhaitez. P>
pdo :: param_str code>, il vous suffit de le spécifier quand il n'est pas une chaîne. De plus,
PDO code> prendra soin de la longueur ici - il n'y a pas de paramètre de longueur. P>
try {
$db = new PDO(...);
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING)
} catch (PDOException $e) {
echo 'Oops, something went wrong with the database connection.';
}
Donc, le bloc d'essai / attraper est-il similaire à une déclaration if / d'autre? Et merci d'avoir souligné les différentes options, cela devrait me donner quelque chose à jouer avec!
Une autre question rapide, quel serait utilisé le code> être utilisé pour, je suppose que vous le référencez pour une erreur?
Pas assez. Si une exception est lancée n'importe où dans le bloc d'essai, il aborte l'exécution du bloc d'essai et exécute le bloc de capture. $ E est l'exception qui a été lancée. Il contient le message d'erreur / code / fichier / ligne, etc. et peut être utilisé pour envoyer un courrier électronique à l'administrateur ou à vous connecter à un fichier afin que vous puissiez enquêter sur ce qui s'est mal passé. Résumé: Essayer / Catch est exceptionnellement bon pour la manipulation des erreurs. Quel jeu de mots haha.
Peut-être la longueur des champs "nom d'utilisateur" et "e-mail"? Par exemple. Si le nom d'utilisateur est Varchar (32), le paramètre de longueur doit être 32.