PHPのMySQLI拡張機能をデータベース操作に使用する場合、前処理ステートメントは一般的で安全な慣行です。開発者は通常、 mysqli :: stmt_init()を使用してステートメントオブジェクトを初期化し、 prepare()メソッドを使用してSQLステートメントを準備します。ただし、 stmt_init()を呼び出した後にprepere()を実行するのを忘れた場合、いくつかの暗黙の問題につながります。この記事では、例を分析して示します。
通常、私たちのコード構造は次のようなものです。
$mysqli = new mysqli("localhost", "user", "password", "database");
$stmt = $mysqli->stmt_init();
$stmt->prepare("SELECT * FROM users WHERE id = ?");
で:
stmt_init() mysqli_stmtオブジェクトを初期化します。
prepare() SQLステートメントを準備し、オブジェクトにバインドします。
stmt_init()のみを呼び出し、 prepare()ではない場合、次のタイプの問題が、次のステートメントの後続の使用でステートメントオブジェクトを使用するときに発生します。
bind_param() 、 execute()などのメソッドを呼び出すことなく、 prepare()を直接execute()は、警告を投げたり、致命的なエラーを引き起こしたりします。
$mysqli = new mysqli("localhost", "user", "password", "database");
$stmt = $mysqli->stmt_init();
// 電話するのを忘れました prepare()
$stmt->bind_param("i", $userId); // ここにエラーが報告されます
$stmt->execute(); // ここでも失敗します
エラーメッセージは次のとおりです。
Fatal error: Uncaught Error: Call to a member function bind_param() on bool
または:
Warning: mysqli_stmt::bind_param(): invalid object or not initialized
ステートメントオブジェクトを初期化するだけでなく、 prece()がない場合、 prepare()ステージで見つかった可能性のあるSQLエラーが非表示になり、実行するまで不明確なエラーにつながらない場合があります。これにより、デバッグコストが増加します。
PREPRE()を使用するのを忘れたことは、SQLステートメントを直接スプライスできることを意味します。これにより、パラメーター結合のメカニズムがバイパスされ、SQL注入のリスクが高まります。例えば:
// エラーの例(いいえ prepare)
$userId = $_GET['id'];
$query = "SELECT * FROM users WHERE id = $userId";
$result = $mysqli->query($query);
PREPERE()およびパラメーターバインディングが使用できない場合、ユーザー入力はSQLに直接埋め込まれ、攻撃者は次のURLを構築できます。
https://m66.net/get_user.php?id=1 OR 1=1
データ侵害を引き起こします。
次のように、常にstmt_init()を使用してペアリングし、 prepare()を使用します。
$mysqli = new mysqli("localhost", "user", "password", "database");
$stmt = $mysqli->stmt_init();
if ($stmt->prepare("SELECT * FROM users WHERE id = ?")) {
$stmt->bind_param("i", $userId);
$stmt->execute();
$result = $stmt->get_result();
while ($row = $result->fetch_assoc()) {
echo $row['username'] . "<br>";
}
$stmt->close();
} else {
echo "SQL prepare 間違い: " . $mysqli->error;
}
prepera()を呼び出すのを忘れて、次の問題が発生します。
他のステートメントメソッドを呼び出すときにエラーが発生しました。
SQLエラーを事前にキャッチすることはできません。
SQLインジェクションなどのセキュリティリスクを増やします。
STMT_INIT()を使用した直後にPREPERE()を呼び出し、プログラムの安定性とセキュリティを確保するためにその返品値を判断することをお勧めします。