Heim  >  Artikel  >  Datenbank  >  So verwenden Sie PDO zum Abfragen von MySQL, um SQL-Injection zu vermeiden

So verwenden Sie PDO zum Abfragen von MySQL, um SQL-Injection zu vermeiden

jacklove
jackloveOriginal
2018-06-09 14:03:501734Durchsuche

Bei Verwendung der herkömmlichen Methoden mysql_connect und mysql_query zum Herstellen einer Verbindung und Abfrage der Datenbank besteht bei nicht strenger Filterung das Risiko einer SQL-Injection. Obwohl die Funktion mysql_real_escape_string() zum Filtern von vom Benutzer übermittelten Werten verwendet werden kann, weist sie auch Mängel auf. Durch die Verwendung der Prepare-Methode der PDO-Erweiterung von PHP können Sie das Risiko einer SQL-Injection vermeiden.

PDO (PHP Data Object) ist eine wichtige neue Funktion, die zu PHP5 hinzugefügt wurde, da PHP4/PHP3 über eine Reihe von Datenbankerweiterungen verfügte, um eine Verbindung zu jeder Datenbankverarbeitung herzustellen , wie zum Beispiel php_mysql.dll. PHP6 verwendet standardmäßig auch PDO zum Herstellen einer Verbindung, und die MySQL-Erweiterung wird als Hilfsmittel verwendet. Offizielle Adresse: http://php.net/manual/en/book.pdo.php

1. PDO-Konfiguration

Bevor Sie die PDO-Erweiterung verwenden, müssen Sie in php.ini zunächst das „;“ vor „extension=php_pdo.dll“ entfernen um das „;“ vor der Datenbankerweiterung „;“ zu entfernen (normalerweise wird php_pdo_mysql.dll verwendet) und dann den Apache-Server neu starten.

extension=php_pdo.dll 
extension=php_pdo_mysql.dll

2. PDO stellt eine Verbindung zur MySQL-Datenbank her

$dbh = new PDO("mysql:host=localhost;dbname=mydb","root","password");

Die Standardeinstellung ist keine lange Verbindung Wenn Sie eine lange Verbindung zur Datenbank haben, können Sie am Ende die folgenden Parameter hinzufügen:

$dbh = new PDO("mysql:host=localhost;dbname=mydb","root","password","array(PDO::ATTR_PERSISTENT => true) "); 
$dbh = null; //(释放)

3. PDO-Einstellungseigenschaften

PDO verfügt über drei Fehlerbehandlungsmethoden:

PDO::ERrmODE_SILENT zeigt keine Fehlermeldungen an, sondern setzt nur Fehlercodes

PDO::ERrmODE_WARNING zeigt Warnfehler an

PDO::ERrmODE_EXCEPTION löst eine Ausnahme aus

Mit der folgenden Anweisung können Sie die Fehlerbehandlungsmethode festlegen, um eine Ausnahme auszulösen

$db->setAttribute(PDO::ATTR_ERrmODE, PDO::ERrmODE_EXCEPTION);

da unterschiedliche Datenbankpaare zurückkehren. Die Groß-/Kleinschreibung von Feldnamen wird unterschiedlich gehandhabt, sodass PDO das Einstellungselement PDO::ATTR_CASE bereitstellt (einschließlich PDO::CASE_LOWER, PDO::CASE_NATURAL, PDO ::CASE_UPPER), um die Groß-/Kleinschreibung des zurückgegebenen Feldnamens zu bestimmen.

Geben Sie den entsprechenden Wert in PHP für den von der Datenbank zurückgegebenen NULL-Wert an, indem Sie den Typ PDO::ATTR_ORACLE_NULLS festlegen (einschließlich PDO::NULL_NATURAL, PDO::NULL_EmpTY_STRING, PDO::NULL_TO_STRING). ).

4. Gängige PDO-Methoden und ihre Anwendungen

PDO::query() wird hauptsächlich für Datensatzoperationen verwendet die Ergebnisse zurückgeben, insbesondere SELECT-Operationen

PDO::exec() sind hauptsächlich für Operationen gedacht, die keine Ergebnismenge zurückgeben, wie INSERT, UPDATE und andere Operationen

PDO::prepare() ist hauptsächlich eine Vorverarbeitungsoperation. Sie müssen $rs->execute() verwenden, um die SQL-Anweisung in der Vorverarbeitung auszuführen. Diese Methode kann Parameter binden und ist relativ leistungsfähig. SQL-Injection verhindern Verlassen Sie sich einfach darauf)

PDO::lastInsertId() gibt den letzten Einfügevorgang zurück, der Typ der Primärschlüsselspalte ist die letzte Auto-Inkrement-ID

PDOStatement::fetch() wird verwendet, um einen Datensatz abzurufen

PDOStatement::fetchAll() wird verwendet, um alle Datensatzsätze in eine Sammlung abzurufen

PDOStatement::fetchColumn() ist ein Feld des ersten im Abrufergebnis angegebenen Datensatzes. Der Standardwert ist das erste Feld

PDOStatement::rowCount (): Wird hauptsächlich verwendet. Die von den DELETE-, INSERT- und UPDATE-Operationen für PDO::query() und PDO::prepare() betroffene Ergebnismenge ist für die PDO::exec()-Methode und die SELECT-Operation ungültig.


5. PDO-Operation MYSQL-Datenbankinstanz

<?php 
$pdo = new PDO("mysql:host=localhost;dbname=mydb","root",""); 
if($pdo -> exec("insert into mytable(name,content) values(&#39;fdipzone&#39;,&#39;123456&#39;)")){ 
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 );
}
?>

Zählen Sie, wie viele Datenzeilen vorhanden sind:

<?php
$sql="select count(*) from table";
$num = $dbh->query($sql)->fetchColumn();
?>

Methode vorbereiten:

e7aacce4249b65e0c0c47d847f142e63prepare("select * from table");
if ($query->execute()) {
    while ($row = $query->fetch()) {
        print_r($row);
    }
}
?>

parametrisierte Abfrage vorbereiten:

<?php
$query = $dbh->prepare("select * from table where id = ?");
if ($query->execute(array(1000))) { 
    while ($row = $query->fetch(PDO::FETCH_ASSOC)) {
        print_r($row);
    }
}
?>

Bei Verwendung von PDO für Um auf die MySQL-Datenbank zuzugreifen, werden standardmäßig keine echten vorbereiteten Anweisungen verwendet. Um dieses Problem zu lösen, müssen Sie die Emulationseffekte vorbereiteter Anweisungen deaktivieren. Hier ist ein Beispiel für die Verwendung von PDO zum Erstellen eines Links:

<?php
$dbh = new PDO(&#39;mysql:dbname=mydb;host=127.0.0.1;charset=utf8&#39;, &#39;root&#39;, &#39;pass&#39;);
$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 &#39;utf8&#39;"); 
$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 = &#39;1,2,3,4,5,6&#39;;
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中文网。

相关推荐:

关于php 双向队列类的讲解

php heredoc 与 nowdoc之间的区别与特点

关于HTML5 localStorage and sessionStorage 之间的区别

Das obige ist der detaillierte Inhalt vonSo verwenden Sie PDO zum Abfragen von MySQL, um SQL-Injection zu vermeiden. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn