前の投稿では、例が期待どおりに機能しなかった理由について既に説明しています。ただし、アプリケーションのセキュリティを向上させる (つまり、SQL インジェクションを防ぐ) ために重要な、データベースを操作する際の適切なコーディング プラクティスがいくつかあります。
次の例は、これらのプラクティスの一部を示すことを目的としており、PHP 5.2 および MySQL 5.1 を想定しています。(すべてのファイルとデータベース エントリは、UTF-8 エンコーディングを使用して保存されることに注意してください。)
この例で使用されるデータベースは と呼ばれtest
、テーブルは次のように作成されました。
CREATE TABLE `test`.`entries` (
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY ,
`data` VARCHAR( 100 ) NOT NULL
) ENGINE = InnoDB CHARACTER SET utf8 COLLATE utf8_bin
(エンコーディングが に設定されていることに注意してくださいutf8_bin
。)
これは、新しいエントリの追加と JSON の作成の両方に使用される php コードに従います。
<?
$conn = new PDO('mysql:host=localhost;dbname=test','root','xxx');
$conn->exec("SET NAMES 'utf8'"); // Enable UTF-8 charset for db-communication ..
if(isset($_GET['add_entry'])) {
header('Content-Type: text/plain; charset=UTF-8');
// Add new DB-Entry:
$data = $conn->quote($_GET['add_entry']);
if($conn->exec('INSERT INTO `entries` (`data`) VALUES ('.$data.')')) {
$id = $conn->lastInsertId();
echo 'Created entry '.$id.': '.$_GET['add_entry'];
} else {
$info = $conn->errorInfo();
echo 'Unable to create entry: '. $info[2];
}
} else {
header('Content-Type: text/json; charset=UTF-8');
// Output DB-Entries as JSON:
$entries = array();
if($res = $conn->query('SELECT * FROM `entries`')) {
$res->setFetchMode(PDO::FETCH_ASSOC);
foreach($res as $row) {
$entries[] = $row;
}
}
echo json_encode($entries);
}
?>
$conn->quote(..)
データをデータベースに渡す前にメソッドを使用することに注意してください。前の投稿で述べたように、プリペアド ステートメントを使用する方が良いでしょう。それらは既にエスケープ処理全体を行っているからです。したがって、次のように記述した方がよいでしょう。
$prepStmt = $conn->prepare('INSERT INTO `entries` (`data`) VALUES (:data)');
if($prepStmt->execute(array('data'=>$_GET['add_entry']))) {...}
それ以外の
$data = $conn->quote($_GET['add_entry']);
if($conn->exec('INSERT INTO `entries` (`data`) VALUES ('.$data.')')) {...}
結論: ユーザーに保存または送信されるすべての文字データに UTF-8 を使用することは合理的です。これにより、国際化された Web アプリケーションの開発がより簡単になります。ユーザー入力がデータベースに適切に送信されていることを確認するには、エスケープ関数を使用することをお勧めします。それ以外の場合、準備済みステートメントを使用すると、SQL インジェクションが防止されるため、作業と開発がさらに容易になり、アプリケーションのセキュリティがさらに向上します。