Lors de l'utilisation des méthodes traditionnelles mysql_connect et mysql_query pour se connecter et interroger la base de données, si le filtrage n'est pas strict, il existe un risque d'injection SQL. Bien que la fonction mysql_real_escape_string() puisse être utilisée pour filtrer les valeurs soumises par l'utilisateur, elle présente également des défauts. En utilisant la méthode de préparation de l'extension PDO de PHP, vous pouvez éviter le risque d'injection SQL.
PDO (PHP Data Object) est une nouvelle fonctionnalité majeure ajoutée à PHP5, car avant PHP 5, php4/php3 disposait de nombreuses extensions de base de données pour se connecter et se connecter à chaque base de données Processing. , tel que php_mysql.dll. PHP6 utilisera également PDO pour se connecter par défaut, et l'extension mysql sera utilisée comme auxiliaire. Adresse officielle : http://php.net/manual/en/book.pdo.php
1. Configuration PDO
Avant d'utiliser l'extension PDO, vous devez d'abord activer cette extension. Dans php.ini, supprimez le ";" devant "extension=php_pdo.dll". pour supprimer le ";" devant l'extension de base de données liée à PDO ";" (généralement php_pdo_mysql.dll est utilisé), puis redémarrez le serveur Apache.
extension=php_pdo.dll extension=php_pdo_mysql.dll
2. PDO se connecte à la base de données MySQL
$dbh = new PDO("mysql:host=localhost;dbname=mydb","root","password");
La connexion par défaut n'est pas longue, si vous souhaitez utiliser une connexion longue à la base de données, vous pouvez ajouter les paramètres suivants à la fin :
$dbh = new PDO("mysql:host=localhost;dbname=mydb","root","password","array(PDO::ATTR_PERSISTENT => true) "); $dbh = null; //(释放)
3. Propriétés de réglage du PDO
PDO dispose de trois méthodes de gestion des erreurs :
PDO::ERrmODE_SILENT n'affiche pas les informations d'erreur, définit uniquement le code d'erreur
PDO ::ERrmODE_WARNING affiche une erreur d'avertissement
PDO::ERrmODE_EXCEPTION lève une exception
Vous pouvez utiliser l'instruction suivante pour définir la méthode de gestion des erreurs sur lancer une exception
$db->setAttribute(PDO::ATTR_ERrmODE, PDO::ERrmODE_EXCEPTION);
Étant donné que différentes bases de données gèrent différemment la casse des noms de champs renvoyés, PDO fournit l'élément de paramètre PDO::ATTR_CASE (y compris PDO::CASE_LOWER, PDO::CASE_NATURAL , PDO::CASE_UPPER) pour déterminer le nom du champ renvoyé en majuscules et en minuscules.
Spécifiez la valeur correspondante en php pour la valeur NULL renvoyée par la base de données en définissant le type PDO::ATTR_ORACLE_NULLS (y compris PDO::NULL_NATURAL, PDO::NULL_EmpTY_STRING, PDO::NULL_TO_STRING ).
4. Méthodes PDO courantes et leurs applications
PDO::query() est principalement utilisé pour les opérations d'enregistrement. qui renvoient des résultats, en particulier les opérations SELECT
PDO::exec() sont principalement destinés aux opérations qui ne renvoient pas de jeu de résultats, telles que INSERT, UPDATE et d'autres opérations
PDO::prepare() est principalement une opération de prétraitement. Vous devez utiliser $rs->execute() pour exécuter l'instruction SQL dans le prétraitement. Cette méthode peut lier des paramètres et est relativement puissante (. empêcher l'injection SQL Fiez-vous simplement à ceci)
PDO::lastInsertId() renvoie la dernière opération d'insertion, le type de colonne de clé primaire est le dernier ID d'auto-incrémentation
PDOStatement::fetch() est utilisé pour obtenir un enregistrement
PDOStatement::fetchAll() est utilisé pour obtenir tous les jeux d'enregistrements dans une collection
PDOStatement::fetchColumn() est un champ du premier enregistrement spécifié dans le résultat de la récupération. La valeur par défaut est le premier champ
PDOStatement::rowCount. () : principalement utilisé. Le jeu de résultats affecté par les opérations DELETE, INSERT et UPDATE sur PDO::query() et PDO::prepare() n'est pas valide pour la méthode PDO::exec() et l'opération SELECT.
5.Opération PDO Instance de base de données MYSQL
<?php $pdo = new PDO("mysql:host=localhost;dbname=mydb","root",""); if($pdo -> exec("insert into mytable(name,content) values('fdipzone','123456')")){ echo "insert success"; echo $pdo -> lastinsertid(); } ?>
<?php $pdo = new PDO("mysql:host=localhost;dbname=mydb","root",""); $rs = $pdo -> query("select * from table"); $rs->setFetchMode(PDO::FETCH_ASSOC); //关联数组形式 //$rs->setFetchMode(PDO::FETCH_NUM); //数字索引数组形式 while($row = $rs -> fetch()){ print_r($row); } ?>
<?php foreach( $db->query( "SELECT * FROM table" ) as $row ) { print_r( $row ); } ?>
Statistiques Combien y a-t-il de lignes de données :
<?php $sql="select count(*) from table"; $num = $dbh->query($sql)->fetchColumn(); ?>
méthode de préparation :
<?php $query = $dbh->prepare("select * from table"); if ($query->execute()) { while ($row = $query->fetch()) { print_r($row); } } ?>
requête paramétrée de préparation :
<?php $query = $dbh->prepare("select * from table where id = ?"); if ($query->execute(array(1000))) { while ($row = $query->fetch(PDO::FETCH_ASSOC)) { print_r($row); } } ?>
Lors de l'utilisation de PDO pour accéder à la base de données MySQL, les véritables instructions préparées ne sont pas utilisées par défaut. Pour résoudre ce problème, vous devez désactiver les effets d'émulation des instructions préparées. Voici un exemple d'utilisation de PDO pour créer un lien :
<?php $dbh = new PDO('mysql:dbname=mydb;host=127.0.0.1;charset=utf8', 'root', 'pass'); $dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES, false); ?>
setAttribute()这一行是强制性的,它会告诉 PDO 禁用模拟预处理语句,并使用 real parepared statements 。这可以确保SQL语句和相应的值在传递到mysql服务器之前是不会被PHP解析的(禁止了所有可能的恶意SQL注入攻击)。
虽然你可以配置文件中设置字符集的属性(charset=utf8),但是需要格外注意的是,老版本的 PHP( < 5.3.6)在DSN中是忽略字符参数的。
完整的代码使用实例:
<?php $dbh = new PDO("mysql:host=localhost; dbname=mydb", "root", "pass"); $dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES, false); //禁用prepared statements的仿真效果 $dbh->exec("set names 'utf8'"); $sql="select * from table where username = ? and password = ?"; $query = $dbh->prepare($sql); $exeres = $query->execute(array($username, $pass)); if ($exeres) { while ($row = $query->fetch(PDO::FETCH_ASSOC)) { print_r($row); } } $dbh = null; ?>
上面这段代码就可以防范sql注入。为什么呢?
当调用 prepare() 时,查询语句已经发送给了数据库服务器,此时只有占位符 ? 发送过去,没有用户提交的数据;当调用到 execute()时,用户提交过来的值才会传送给数据库,它们是分开传送的,两者独立的,SQL攻击者没有一点机会。
但是我们需要注意的是以下几种情况,PDO并不能帮助你防范SQL注入。
不能让占位符 ? 代替一组值,这样只会获取到这组数据的第一个值,如:
select * from table where userid in ( ? );
如果要用in來查找,可以改用find_in_set()实现
$ids = '1,2,3,4,5,6'; select * from table where find_in_set(userid, ?);
不能让占位符代替数据表名或列名,如:
select * from table order by ?;
不能让占位符 ? 代替任何其他SQL语法,如:
select extract( ? from addtime) as mytime from table;
本篇文章如何使用PDO查询mysql避免SQL注入的方法,更多相关内容请关注php中文网。
相关推荐:
关于HTML5 localStorage and sessionStorage 之间的区别
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!