34

最小限のデータベースを使用する PHP 駆動の Web サイトを再設計しています。元のバージョンでは、"pseudo-prepared-statements" (クォートとパラメーターの置換を行う PHP 関数) を使用して、インジェクション攻撃を防ぎ、データベース ロジックをページ ロジックから分離していました。

これらのアドホック関数を、PDO と実際のプリペアード ステートメントを使用するオブジェクトに置き換えるのは当然のことのように思えましたが、それらについて読んだ後では、よくわかりません。PDO は依然として素晴らしいアイデアのように思えますが、プリペアド ステートメントの主なセールス ポイントの 1 つは、それらを再利用できることです。これが私のセットアップです:

  • ステートメントはすべて自明です。ほとんどは の形式SELECT foo,bar FROM baz WHERE quux = ? ORDER BY bar LIMIT 1です。多くの中で最も複雑なステートメントは、s で結合された 3 つの selectUNION ALLです。
  • 各ページ ヒットは、多くても1 つのステートメントを実行し、1 回だけ実行します。
  • 私はホストされた環境にいるため、個人的に「ストレステスト」を行ってサーバーを非難することに不安を感じています.

プリペアド ステートメントを使用すると、データベースへの往復回数が少なくとも 2 倍になることを考えると、それらを避けたほうがよいでしょうか? PDO::MYSQL_ATTR_DIRECT_QUERYパラメータ化とインジェクション防御の利点を維持しながら、複数のデータベーストリップのオーバーヘッドを回避するために使用できますか? それとも、準備されたステートメント API で使用されるバイナリ呼び出しは、準備されていないクエリを実行する場合と比較して、心配する必要がないほど十分に機能しますか?

編集:

皆さん、良いアドバイスをありがとう。これは、複数の回答を「承認済み」としてマークできたらいいのにと思います。さまざまな視点がたくさんあります。しかし、最終的には、私はリックに当然のことをしなければなりません... 彼の答えがなければ、私は幸せに立ち去り、みんなのアドバイスに従ったとしても、完全に間違ったことをしたでしょう. :-)

エミュレートされた準備済みステートメントです。

4

6 に答える 6

25

今日のソフトウェア エンジニアリングのルールは、「役に立たないものは使用しない」というものです。

于 2009-02-11T05:39:45.273 に答える
18

PDO::ATTR_EMULATE_PREPARES が必要だと思います。これにより、ネイティブ データベースのプリペアド ステートメントがオフになりますが、クエリ バインディングによって SQL インジェクションが防止され、SQL が整理された状態に保たれます。私が理解していることから、PDO::MYSQL_ATTR_DIRECT_QUERY はクエリ バインディングを完全にオフにします。

于 2009-02-11T17:13:07.417 に答える
15

準備済みステートメントを使用しない場合 データベース接続がなくなる前にステートメントを 1 回だけ実行する場合。

バインドされたクエリ パラメータを使用しない場合(これは、ほとんどの人が準備済みステートメントを使用して取得するものです)。私は「決して」と言いがちで、本当に「決して」と言いたいのですが、現実には、ほとんどのデータベースと一部のデータベース抽象化レイヤーには、パラメーターをバインドできない特定の状況があるため、これらの場合、それらを使用しないことを余儀なくされています。ただし、それ以外の場合は、生活がよりシンプルになり、コードをより安全に使用できるようになります。

私は PDO に精通していませんが、準備したくない場合は、同じ関数呼び出しで指定された値を使用してパラメーター化されたクエリを実行し、別のステップとして実行するためのメカニズムを提供するに違いありません。(例:run_query("SELECT * FROM users WHERE id = ?", 1)似たようなもの。)

また、内部を見ると、静的 SQL ステートメントを実行するように指示しただけでも、ほとんどの db 抽象化レイヤーはクエリを準備してから実行します。したがって、とにかく明示的な準備を回避することで、おそらくデータベースへの旅行を節約していません。

于 2009-02-11T17:39:20.410 に答える
10

準備されたステートメントは何千人もの人々によって使用されているため、十分にテストされています (したがって、合理的に安全であると推測できます)。カスタム ソリューションは、あなただけが使用します。

カスタム ソリューションが安全でない可能性はかなり高いです。準備済みステートメントを使用します。そのように維持するコードを少なくする必要があります。

于 2009-02-11T09:58:19.113 に答える
7

準備済みステートメントの利点は次のとおりです。

  • 各クエリは一度だけコンパイルされます
  • mysql は、より効率的なトランスポート形式を使用してデータをサーバーに送信します。

ただし、準備済みステートメントは接続ごとにのみ保持されます。接続プーリングを使用していない限り、ページごとに 1 つのステートメントしか実行していない場合、メリットはありません。単純なクエリも、より効率的なトランスポート形式の恩恵を受けません。

個人的には気にしません。擬似的に準備されたステートメントは、それらが提供すると思われる安全な変数の引用に役立つ可能性があります。

于 2009-02-11T15:35:56.993 に答える
2

正直、気にしなくていいと思います。ただし、多くの PHP データ アクセス フレームワークが準備ステートメント モードと非準備ステートメント モードをサポートしていたことを覚えています。私の記憶が正しければ、PEAR:DB は昔のことです。

私はあなたと同じ問題に遭遇し、私自身の予約があったので、PDOを使用する代わりに、準備と標準ステートメントをサポートし、両方で正しいエスケープ(SQLインジェクション防止)を実行する独自の軽量データベースレイヤーを作成することになりましたケース。準備に関する私の他の不満の 1 つは、エスケープ不可能な入力を ... WHERE id IN (1, 2, 3...) のようなステートメントに追加する方が効率的な場合があるということです。

PDO については、他にどのようなオプションがあるかを説明できるほど詳しくありません。ただし、PHP には、サポートしているすべてのデータベース ベンダーで使用できるエスケープ関数があり、スタックしているデータ アクセス レイヤーの上に独自の小さなレイヤーを展開できることは知っています。

于 2009-02-11T09:12:00.487 に答える