P粉8912379122023-08-23 00:21:40
パラメータ化されたクエリを使用するには、Mysqli または PDO を使用する必要があります。 mysqli を使用して例を書き直すには、次のようなコードが必要になります。
リーリー読んでおきたい重要な関数は mysqli::prepare
です。
また、他の人が示唆しているように、PDO のような高レベルの抽象化レイヤーを使用する方が便利/簡単であると思われるかもしれません。
あなたが言及した状況は非常に単純ですが、より複雑な状況ではより洗練された方法が必要になる可能性があることに注意してください。特に:###
に含まれていません。この場合、ユーザーの入力をホワイトリストに渡して、「安全な」値のみが許可されるようにすることをお勧めします。
P粉7712333362023-08-23 00:20:03
どのデータベースを使用する場合でも、SQL インジェクション攻撃を回避する 正しい 方法は、 データを SQL から分離することです そうすることで、データはデータの形式で残り、 は SQL では使用できません。パーサーは をコマンドとして解釈します。適切にフォーマットされたデータ部分を使用して SQL ステートメントを作成することは可能ですが、詳細を 完全に理解していない場合は、常に プリペアド ステートメントとパラメーター化されたクエリ を使用する必要があります。これらは、パラメーターとは別に送信され、データベース サーバーによって分析される SQL ステートメントです。これにより、攻撃者は悪意のある SQL を挿入できなくなります。
これを実現するには基本的に 2 つの方法があります:
の使用 (MySQL の場合):
PHP 8.2 以降、
execute_query() メソッドを使用して、パラメータを準備、バインドし、SQL ステートメントを実行できます。
リーリー
PHP8.1 より前:
MySQL 以外のデータベースに接続している場合は、2 番目のドライバー固有のオプションを参照できます (たとえば、PostgreSQL の場合は、
pg_prepare())。 PDO はユニバーサル オプションです。
接続を正しく設定してください
PDO: を使用して接続を作成する例です。 リーリー 上記の例では、エラー モードは厳密には必須ではありませんが、 追加することをお勧めします。このようにして、PDO は PDOException をスローしてすべての MySQL エラーを通知します。
ただし、 が行う必要があるのは、最初の行 setAttribute() です。これは、PDO に、シミュレートされたプリペアド ステートメントを無効にし、
実際の
コンストラクターのオプションで charset を設定できますが、PHP の「古い」バージョン (5.3.6 より前)
は DSN の charset 引数を黙って無視することに注意することが重要です。 ###。
Mysqli
mysqli の場合、同じルーチンに従う必要があります:
リーリー
###説明する###
prepare
:name
のような名前付きパラメーター) を指定することにより、フィルターする場所をデータベース エンジンに指示します。次に、ここで重要なのは、SQL 文字列との組み合わせではなく、パラメーター値とコンパイルされたステートメントの組み合わせです。 SQL インジェクションは、データベースに送信する SQL を作成するときに、スクリプトをだまして悪意のある文字列を含めることによって機能します。したがって、実際の SQL をパラメータとは別に送信することで、予期しない結果が発生するリスクを制限できます。 プリペアド ステートメントを使用して送信されたパラメータはすべて文字列として扱われます (ただし、データベース エンジンはパラメータに対して何らかの最適化を実行するため、パラメータが数値になる可能性があります)。上記の例では、
リーリー
リーリー$name
変数に 'Sarah'; DELETE FROMemployees
が含まれている場合、結果は検索文字列 "'Sarah'; DELETE FROMemployee のみになります。 "
、空のテーブルは得られません。
準備されたステートメントは動的クエリに適していますか?
プリペアド ステートメントをクエリ パラメーターに使用することはできますが、動的クエリ自体の構造はパラメーター化できず、特定のクエリ関数はパラメーター化できません。