プリペアドステートメントは、MySQL インジェクションを防ぐのに非常に役立ちます。
SQL インジェクション は、Web フォームの送信に SQL コマンドを挿入したり、ページ リクエストのドメイン名やクエリ文字列を入力したりして、最終的にサーバーをだまして悪意のある SQL コマンドを実行させることです。
プリペアドステートメントとバインドパラメータ
プリペアドステートメントは、複数の同一の SQL ステートメントをより高い実行効率で実行するために使用されます。
準備されたステートメントの動作原理は次のとおりです:
1. 前処理: SQL ステートメントのテンプレートを作成し、データベースに送信します。予約された値にはパラメータ「?」が付けられます。例:
INSERT INTO MyGuests (firstname, lastname, email) VALUES(?, ?, ?)
2. SQL ステートメント テンプレートでのデータベースの解析、コンパイル、クエリの最適化、および出力を行わない結果の保存。パラメータ値が異なる場合、アプリケーションはステートメントを複数回実行できます。
3. 実行: 最後に、アプリケーションにバインドされた値をパラメーター (「?」マーク) に渡すと、データベースがステートメントを実行します。
SQL ステートメントを直接実行する場合と比較して、プリペアド ステートメントには 2 つの主な利点があります
· プリプロセスされたステートメントにより、分析時間が大幅に短縮され、クエリが 1 つだけ作成されます (ただし、ステートメントは複数回実行されます)。
· パラメーターをバインドするとサーバーの帯域幅が削減され、ステートメント全体ではなくクエリのパラメーターのみを送信する必要があります。
· プリペアド ステートメントは、パラメーター値が送信された後にさまざまなプロトコルが使用され、データの合法性が保証されるため、SQL インジェクションに非常に役立ちます。
MySQLi プリペアド ステートメント
次の例では、MySQLi でプリペアド ステートメントを使用し、対応するパラメーターをバインドします。
<?php header("Content-type:text/html;charset=utf-8"); //设置编码 $servername = "localhost"; $username = "root"; $password = "root"; $dbname = "test"; // 创建连接 $conn = new mysqli($servername, $username, $password, $dbname); // 检测连接 if ($conn->connect_error) { die("连接失败: " . $conn->connect_error); } // 预处理及绑定 $stmt = $conn->prepare("INSERT INTO MyGuests (firstname, lastname, email) VALUES(?, ?, ?)"); $stmt->bind_param("sss", $firstname, $lastname, $email); // 设置参数并执行 $firstname = "John"; $lastname = "Doe"; $email = "john@example.com"; $stmt->execute(); $firstname = "Mary"; $lastname = "Moe"; $email = "mary@example.com"; $stmt->execute(); $firstname = "Julie"; $lastname = "Dooley"; $email = "julie@example.com"; $stmt->execute(); echo "新记录插入成功"; $stmt->close(); $conn->close(); ?>
次の例のコードの各行を解析します。
"INSERT INTO MyGuests (firstname, lastname, email) VALUES(?, ?, ?)"SQL ステートメントでは疑問符 (?) を使用します。ここで疑問符を整数や文字列に置き換えることができます。 、double、およびブール値。
次に、bind_param() 関数を見てみましょう:
$stmt->bind_param("sss", $firstname, $lastname, $email);この関数は SQL にバインドされていますパラメータを取得し、データベースにパラメータの値を伝えます。 「sss」パラメータ列は、残りのパラメータのデータ型を処理します。上にはいくつかのデータ型があり、s 文字はデータベースにパラメータが文字列であることを示します。
パラメータには以下の4種類があります:
・ i - integer (整数型)
・ d - double (倍精度浮動小数点型)
・ s - string (文字列)
・ b - BLOB (バイナリ ラージ オブジェクト) :Binary Large Object)
各パラメータには型を指定する必要があります。
データ型の指定方法は前のセクションで紹介しました
データベースパラメータのデータ型を伝えることで、SQLインジェクションのリスクを軽減できます。
上記のコードの実行結果:
新しいレコードが正常に挿入されました
データが正常に挿入されたかどうか確認しますか?
例
フォーム内のデータをデータベースに挿入しましょう
まず、HTMLページ
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>PHP中文网</title> </head> <body> <form action="insert.php" method="post"> Firstname: <input type="text" name="firstname" /><br/> Lastname: <input type="text" name="lastname" /><br/> email: <input type="text" name="email" /><br/> <input type="submit" /> </form> </body> </html>
それをPHPページに送信します
<?php header("Content-type:text/html;charset=utf-8"); //设置编码 $servername = "localhost"; $username = "root"; $password = "root"; $dbname = "test"; // 创建连接 $conn = new mysqli($servername, $username, $password, $dbname); // 检测连接 if ($conn->connect_error) { die("连接失败: " . $conn->connect_error); } // 预处理及绑定 $stmt = $conn->prepare("INSERT INTO MyGuests (firstname, lastname, email) VALUES(?, ?, ?)"); $stmt->bind_param("sss", $firstname, $lastname, $email); // 设置参数并执行 $firstname = $_POST['firstname']; $lastname =$_POST['lastname']; $email = $_POST['email']; $stmt->execute(); echo "新记录插入成功"; $stmt->close(); $conn->close(); ?>
上記の2つの手順を通じて、次のことができますフォームのデータをデータベースに挿入します データがデータベースに挿入されました