従来の mysql_connect および mysql_query メソッドを使用してデータベースに接続してクエリを実行する場合、フィルタリングが厳密でないと SQL インジェクションのリスクがあり、Web サイトが攻撃されて制御不能になります。 mysql_real_escape_string() 関数はユーザーが送信した値をフィルタリングするために使用できますが、これにも欠陥があります。 PHPのPDO拡張機能のprepareメソッドを使用することで、SQLインジェクションのリスクを回避できます。
PDO (PHP Data Object) は、PHP5 に追加された主要な新機能です。PHP 5 より前では、php4/php3 には、php_mysql.dll など、さまざまなデータベースに接続して処理するためのデータベース拡張機能が多数含まれていたためです。 PHP6 もデフォルトで PDO を使用して接続し、mysql 拡張機能が補助として使用されます。公式: http://php.net/manual/en/book.pdo.php
1. PDO の設定
データベースに接続するには、PHP.ini でこの拡張機能を有効にする必要があります。データベース拡張子 (通常は php_pdo_mysql.dll が使用されます) の前にある PDO 関連の「;」記号も削除し、Apache サーバーを再起動する必要があります。
コードをコピー コードは次のとおりです:
extension=php_pdo.dll
extension=php_pdo_mysql.dll
2. PDO は mysql データベースに接続します
コードをコピー コードは次のとおりです:
$dbh = new PDO("mysql:host=localhost;dbname=db_demo","root","password");
を使用する場合、デフォルトは長い接続ではありません。データベースへの接続が長い場合は、最後に次のパラメータを追加する必要があります:
コードをコピーします コードは次のとおりです:
$dbh = new PDO("mysql:host=localhost;dbname =db_demo","root","password","array(PDO::ATTR_PERSISTENT => true )");
$dbh = null; //(release)
3. PDO 設定プロパティ
1) PDO には 3 つのエラー処理方法があります:
• PDO::ERrmODE_SILENT はエラー メッセージを表示せず、エラー コードのみを設定します
• PDO::ERrmODE_WARNING は警告エラーを表示します
• PDO::ERrmODE_EXCEPTION は例外をスローします
次のステートメントを使用して、例外をスローするエラー処理メソッドを設定できます
コードをコピーします コードは次のとおりです:
$db->setAttribute(PDO::ATTR_ERrmODE, PDO:: ERrmODE_EXCEPTION);
Dang PDO::ERrmODE_SILENT に設定すると、errorCode() または errorInfo() を呼び出すことでエラー情報を取得できます。もちろん、他の状況でも使用できます。
2) データベースが異なると、返されるフィールド名の大文字と小文字の処理が異なるため、PDO には、返されるフィールド名の大文字と小文字を決定するための PDO::ATTR_CASE 設定項目 (PDO::CASE_LOWER、PDO::CASE_NATURAL、PDO::CASE_UPPER を含む) が用意されています。 。
3) PDO::ATTR_ORACLE_NULLS タイプ (PDO::NULL_NATURAL、PDO::NULL_EmpTY_STRING、PDO::NULL_TO_STRING を含む) を設定して、データベースから返される NULL 値に対応する値を php で指定します。
4. 一般的な PDO メソッドとそのアプリケーション
PDO::query() は主に記録された結果を返す操作、特に SELECT 操作に使用されます
PDO::exec() は主に結果セットを返さない操作に使用されますINSERT、UPDATE などの操作
PDO::prepare() は主に前処理操作であり、$rs->execute() を介して前処理で SQL ステートメントを実行する必要があります。強力 (SQL インジェクションの防止はこれに依存します)
PDO::lastInsertId() は最後の挿入操作を返します。主キーの列の型は最後に自動インクリメントされた ID です
PDOStatement::fetch() はレコードを取得するために使用されます
PDOStatement: :fetchAll() は、すべてのレコードセットをコレクションに取得します
PDOStatement::fetchColumn() は、結果で指定された最初のレコードのフィールドを取得します。デフォルトは最初のフィールドです
PDOStatement::rowCount(): 主にPDO に使用: :query() および PDO::prepare() の DELETE、INSERT、および UPDATE 操作の影響を受ける結果セットは、PDO::exec() メソッドおよび SELECT 操作では無効です。
5. PDO は MYSQL データベース インスタンスを操作します
コードをコピーします コードは次のとおりです:
$pdo = new PDO("mysql:host=localhost;dbname=db_demo", "root" ,"");
if($pdo -> exec("db_demo(name,content) に挿入 value('title','content')")){
echo "挿入成功!";
echo $pdo -> lastinsertid();
}
?>
コードをコピーします コードは次のとおりです:
$pdo = new PDO("mysql:host=localhost;dbname=db_demo","root","");
$rs = $pdo -> query("select * from test" );
$rs->setFetchMode(PDO::FETCH_ASSOC); //連想配列形式
//$rs->setFetchMode(PDO::FETCH_NUM) //数値インデックス配列形式
while($row = $ rs -> fetch()){
print_r($row);
}
?>
コードをコピー コードは次のとおりです:
foreach( $db -> query( "SELECT * FROM feeds" ) as $row )
{
print_r( $row );
}
?>
データの行数を数えます
コードをコピーします コードは次のとおりです:
$sql="select count(*) from test";
$num = $dbh->query($sql)->fetchColumn();
メソッドを準備します
コードをコピー コードは次のとおりです:
$stmt = $dbh->prepare("select * from test");
if ($stmt->execute()) {
while ( $row = $stmt->fetch()) {
print_r($row);
}
}
パラメータ化されたクエリを準備します
コードをコピーします コードは次のとおりです:
$stmt = $dbh->prepare("select * from test where name = ?");
if ($stmt->execute(array("david"))) {
while ($row = $stmt->fetch (PDO::FETCH_ASSOC)) {
print_r($row);
}
}
【重要なポイント、SQL インジェクションを防ぐ方法について話しましょう】
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 (
完全なコード使用例を見てみましょう:
コードをコピーします コードは次のとおりです:
$dbh = new PDO("mysql:host=localhost; dbname=demo", "user ", "pass" );
$dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES, false); //プリペアドステートメントのシミュレーション効果を無効にする
$dbh->exec("set names 'utf8'");
$sql="名前 = ? およびパスワード = ? のテストから * を選択";
$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() が呼び出されるとき、ユーザーによって送信されるデータはありません。ユーザーによる送信はデータベースに個別に送信され、SQL 攻撃者は両者に独立した攻撃を行う可能性はありません。
ただし、次の状況には注意する必要があります。PDO では SQL インジェクションを防ぐことができません。
1. プレースホルダー ? を次のような値のセットに置き換えることはできません:
コードは次のとおりです: SELECT * FROM blog WHERE userid IN ( ? );
2. 次のようなデータ テーブル名や列名をプレースホルダーに置き換えることはできません:
コードをコピーします
コードは次のとおりです: SELECT * FROM blog ORDER BY ?;
3プレースホルダー ? を他の SQL 構文に置き換えることはできません:
コードをコピーします
コードは次のとおりです:
SELECT EXTRACT( ? FROM datetime_column) AS variable_datetime_element FROM blog;
http://www.bkjia.com/PHPjc/326795.htmlwww.bkjia.comtruehttp://www.bkjia.com/PHPjc/326795.html技術記事従来の mysql_connect および mysql_query メソッドを使用してデータベースに接続してクエリを実行する場合、フィルタリングが厳密でないと SQL インジェクションのリスクがあり、Web サイトが攻撃されて制御不能になります。それは可能ですが...