8

私は次のような機能を持っています

function getInfoById($id, $info) {

}

アイデアは、クエリを"SELECT $info FROM table WHERE id = $id"

列名をエスケープできないため、これは PDO では機能しません。"SELECT *"また、より大きな結果セットを返し、より多くのメモリを使用しないため、実際には使用したくありませんか?

4

3 に答える 3

15

はい、PDO には、テーブル名や列名などの識別子を区切るための組み込み関数がありません。このPDO::quote()関数は、文字列リテラルと日付リテラル専用です。

ちなみに、Zend Framework に取り組んでいたときに、quoteIdentifier()関数を実装しました。

SELECT *おそらくより多くのメモリを使用し、インデックスをカバーする利点を損なう可能性があります。

列名をホワイトリストに登録することをお勧めします。つまり、$info が実際に の列に名前を付けていることを確認してくださいtable。そうすれば、列名が存在しないことや、奇妙な文字が含まれていることなどについて心配する必要はありません。クエリに入れる正当な列のセットを制御できます。

いずれにせよ、列名も区切る必要があります。列名に句読点、空白、国際文字が含まれている場合、または SQL 予約語と一致する場合は、区切り識別子が必要です。異なるデータベースは異なる名前の引用符を使用していますか?を参照してください。

function getInfoById($id, $info) {
    // you can make this a literal list, or query it from DESC or INFORMATION_SCHEMA
    $cols = array('col1', 'col2', 'col3');

    if (array_search($info, $cols) === false) {
      return false;
    }
    $sql = "SELECT `$info` FROM table WHERE id = :id";
    $stmt = $pdo->prepare($sql);
    if ($stmt === false) {
      return false;
    }
    . . .
}

私のプレゼンテーションSQL Injection Myths and Fallaciesで、ホワイトリスト登録の例をさらに示します。

于 2012-11-19T05:57:56.847 に答える
6

正規表現でそれを除外するだけです。複雑にしないでおく。

また、バインド$idして持っている必要があります:id

$info = preg_replace('/[^A-Za-z0-9_]+/', '', $info);

$stmt = $pdo->prepare('SELECT $info FROM table WHERE id = :id'); 
$stmt->bindParam(':id', $id);
$stmt->execute();
于 2012-11-19T05:45:15.077 に答える