PDO を使用して MySQL データベースにアクセスする場合、デフォルトでは実際のプリペアド ステートメントは使用されません。この問題を解決するには、準備されたステートメントのエミュレーション効果を無効にする必要があります。 PDO を使用してリンクを作成する例を次に示します:
コードは次のとおりです:
$dbh = new PDO('mysql:dbname=dbtest;host=127.0.0.1;charset=utf8', 'user', 'pass'); $dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
setAttribute() この行は必須であり、プリペアド ステートメントのエミュレーションを無効にし、実際のペアペア ステートメントを使用するように PDO に指示します。これにより、SQL ステートメントと対応する値が mysql サーバーに渡される前に PHP によって解析されなくなります (考えられるすべての悪意のある SQL インジェクション攻撃を無効にします)。構成ファイルで文字セット属性 (charset=utf8) を設定できますが、古いバージョンの PHP (<5.3.6) では DSN の文字パラメータが無視されることに注意してください。
完全なコードの使用例を見てみましょう:
コードは次のとおりです:
$dbh = new PDO("mysql:host=localhost; dbname=dbtest", "user", "pass"); $dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES, false); //禁用prepared statements的仿真效果 $dbh->exec("set names 'utf8'"); $sql="select * from test where name = ? and password = ?"; $stmt = $dbh->prepare($sql); $exeres = $stmt->execute(array($testname, $pass)); if ($exeres) { while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) { print_r($row); } } $dbh = null;
上記のコードは SQL インジェクションを防ぐことができます。なぜ?
prepare() が呼び出されるとき、クエリ ステートメントはデータベース サーバーに送信されます。この時点では、execute() が呼び出されるとき、ユーザーによって送信されるデータはありません。と呼ばれる、ユーザーによって送信されたデータはデータベースに送信され、それらは別々に送信され、2 つは独立しており、SQL 攻撃者には攻撃の余地がありません。
しかし、次のような状況には注意する必要があります。PDO は SQL インジェクションを防ぐことができません
1。次のような値のセットを置き換えることはできません。コードは次のとおりです。
SELECT * FROM blog WHERE userid IN ( ? );
コードは次のとおりです。
SELECT * FROM blog ORDER BY ?;
コードは次のとおりです:
SELECT EXTRACT( ? FROM datetime_column) AS variable_datetime_element FROM blog;