47

コードを から に変更していmysql_*ますPDO。私のコードでは、mysql_real_escape_string(). PDOでこれに相当するものは何ですか?

4

6 に答える 6

72

いいえ、ありません!

技術的にはありますPDO::quote()が、めったに使用されず、同等ではありませんmysql_real_escape_string()

それは正しい!準備済みステートメントを使用して文書化されているように、すでに PDO を適切な方法で使用している場合は、MySQL インジェクションから保護されます。


#Example:

以下は、準備済みステートメント (pdo) を使用した安全なデータベース クエリ の例です。

  try {
     // first connect to database with the PDO object. 
     $db = new \PDO("mysql:host=localhost;dbname=xxx;charset=utf8", "xxx", "xxx", [
       PDO::ATTR_EMULATE_PREPARES => false, 
       PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
     ]); 
 } catch(\PDOException $e){
     // if connection fails, show PDO error. 
   echo "Error connecting to mysql: " . $e->getMessage();
 }

そして、接続が確立されたと仮定すると、次のようにクエリを実行できます。

if($_POST && isset($_POST['color'])){ 

    // preparing a statement
    $stmt = $db->prepare("SELECT id, name, color FROM Cars WHERE color = ?");

    // execute/run the statement. 
    $stmt->execute(array($_POST['color']));

    // fetch the result. 
    $cars = $stmt->fetchAll(\PDO::FETCH_ASSOC); 
    var_dump($cars); 
 }

おそらくおわかりのように、 の値をエスケープ/サニタイズするために何も使用していません$_POST["color"]。そして、このコードは、PDO とプリペアド ステートメントの力のおかげで、myql インジェクションから保護されています。


セキュリティ上の理由から、上記のようにcharset=utf8as 属性を渡す必要があり、常に PDO が例外の形式でエラーを表示できるようにする必要があることに注意してください。DSN

PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION

そのため、データベース クエリのエラーによって、ディレクトリ構造やデータベースのユーザー名などの機密データが明らかになることはありません。

最後になりましたが、PDO を 100% 信頼してはならず、SQL インジェクションを防ぐために追加の手段を講じる必要がある場合があります。そのようなケースの 1 つは、この記事で説明されている古いバージョンの mysql を使用している場合[ mysql =< 5.3.6 ]です。答え

ただし、上記のように準備されたステートメントを使用することは、で始まる関数を使用するよりも常に安全です。mysql_

良い読み取り

MySQL 開発者向け PDO チュートリアル

于 2012-12-23T16:38:23.733 に答える
28

なにもない*!PDO の目的は、何もエスケープする必要がないことです。データとして送信するだけです。例えば:

$query = $link->prepare('SELECT * FROM users WHERE username = :name LIMIT 1;');
$query->execute([':name' => $username]); # No need to escape it!

とは対照的に:

$safe_username = mysql_real_escape_string($username);
mysql_query("SELECT * FROM users WHERE username = '$safe_username' LIMIT 1;");

* まあ、Michael Berkowski が言ったように、1 つあります。しかし、もっと良い方法があります。

于 2012-12-23T16:34:19.240 に答える
-1

ここで多くの人のコメントに応えて、まだ直接コメントすることはできませんが (50 ポイントに達していません)、実際には$dbh->quote($value)PDO を使用するときに EVEN を使用する必要があり、それらは完全に正当な理由です...

  1. MySQL/Maria Db の InnoDb テーブルを悪用するため、「BULK INSERT」コマンドを構築する多くのレコードをループしている場合 (通常は 1000 レコードで再起動します)。プリペアド ステートメントを使用して個々の挿入コマンドを作成するのは便利ですが、大量のタスクを実行する場合は非常に非効率的です。
  2. PDO はまだ動的な IN(...) 構造体を扱うことができないため、ユーザー変数のリストから IN 文字列のリストを作成する場合、$dbh->quote($value)リスト内の各値を使用する必要があります!

そうです、$dbh->quote($value)PDO を使用する場合は必要であり、おそらくコマンドが最初に使用できる理由です。

PS、コマンドを引用符で囲む必要はありませ$dbh->quote($value)ん。コマンドもそれを行います。

外。

于 2019-09-04T09:58:38.107 に答える