web-dev-qa-db-ja.com

$ wpdb->はエスケープするのに多くの準備ができていますか?正しく使うには?

Imは$ wpdb-> prepareで混乱しています。ユーザー入力をサニタイズするために使用したいのですが、クエリが破壊されることがわかりました。これがどのように機能することを意図しているのか想像することはできませんが、自分が間違っていることを見つけることはできません。辛抱強くして、解決策を教えてください。次のコードは、デモンストレーションを目的とした単純な例にすぎません。これは、何が問題でどのように発生しているのかを明確にするためです。 後でこのクエリを入力するユーザー入力があります。

代わりにsprintfの準備と使用を省略した場合、この例は機能します。

global $wpdb;
$mydb = new \wpdb( "My_Login" ,"My_PW" , "My_Custom_DB" ,"localhost"); //wpdb instance for my custom db

$tablename = "books";
$sort_direction = "DESC";
$limit = 5;   
$sqlquery = sprintf( "SELECT * FROM %s ORDER BY datum %s LIMIT %d", $tablename, $sort_direction, $limit );

$res = $mydb->get_results( $sqlquery );
echo "<br>".$sqlquery."<br>";
var_dump($res);

Var_dump()の出力は、期待される結果を含む適切な配列です。

$ sqlqueryの出力は次のとおりです。

SELECT * FROM books ORDER BY datum DESC LIMIT 5

これは正しいSQLです。

今度はprepareを使用します(これが唯一の変更された行です)。

global $wpdb;
$mydb = new \wpdb( "My_Login" ,"My_PW" , "My_Custom_DB" ,"localhost"); //wpdb instance for my custom db

$tablename = "books";
$sort_direction = "DESC";
$limit = 5;   
$sqlquery = $mydb->prepare( "SELECT * FROM %s ORDER BY datum %s LIMIT %d", $tablename, $sort_direction, $limit );

$res = $mydb->get_results( $sqlquery );
echo "<br>".$sqlquery."<br>";
var_dump($res);

Var_dump()の出力は、NULLです。

$ sqlqueryの出力は次のとおりです。

SELECT * FROM 'books' ORDER BY datum 'DESC' LIMIT 5

明らかにテーブル名とDESCを引用符で囲まないでください。 IMOこれが失敗する理由です。私はこれが$ wpdbのインスタンス化に関連していないことを再確認しました。私が$ wpdbを使って作業しているときのエスケープ結果は同じです。

何が起こっているのか、何が間違っていましたか?私を助けてください。

2
Hexodus

あなたがここで間違ったことは、そもそもそれらのアイテムを準備することでした。

あなたはprepare()を通して "data"変数を実行するだけです。あなたはテーブル名を走らせたり、方向をソートしたり、それを通して制限したりしません。これらはSQLコマンド自体の一部であり、データベースの列に格納されている情報を参照するデータではありません。

SELECTクエリにはデータ入力がありません...そのため、準備できる入力はありません。

SELECTの特定のケースでは、データはWHERE句の中のものです。 column =%sなどです。これは可変的なデータであり、おそらくユーザー入力から来る可能性があるため安全ではありません。そのため、データは安全にするための準備を経て実行される必要があります。しかし、あなたが注文のためにハードコードされた「DESC」を持っているならば、準備を通してそれを実行する意味がありません。それは「DESC」です。それは安全です。あなたがそれが何であるかを知らないデータだけが安全ではありません。

編集:それは、データがユーザー入力から来る場合、ユーザーが表示する項目の数を選択できる場合のように、そのデータはサニタイズされなければなりません。そのため、制限は整数であり、ユーザーが "5"または "10"を選択したことに起因する可能性があるため、prepareを通じて実行できます。

ただし、ユーザーがテーブル名やソート順を直接入力することはできません。彼らはものを表示する方向を選びますが、あなたはそれをASCかDESCに変換するでしょう。彼らは「本」を直接選ぶのではなく、あなたが「本」と解釈するリストから選ぶかもしれません。そのようなこと。

3
Otto