1

MySQL クエリの URL を介して特殊な記号を渡す必要があります。たとえば、次のような URL が必要です。

www.example.com/index.php?q=AND name LIKE '%hi%'

最初に試したところ、406 エラーが発生しました。私はそれを調べましたが、どうやら and を使用する必要があるようurlencode()ですurldecode()。それらを入れると、406エラーはなくなりましたが、MySQLエラーが発生しました:

mysql_fetch_array(): supplied argument is not a valid MySQL result resource

通常、これらを取得すると、クエリが正しく記述されていないことを意味します。だから私はMySQLクエリをエコーし​​ 、すべてがうまく見えました。urldecode()ページに渡したいものを削除して、変数にハードコーディングしたところ、MySQL エラーはなくなりました。ただし、使用するクエリと使用urldecode()しないクエリの両方がまったく同じであるため、少し混乱しています。

の php.net ドキュメント ページに移動したところ、と を一緒に使用すると予期しない結果になる可能性urldecode()があるという警告があり、それは既にデコーダーとして機能している (または、少なくとも私はそのように文言を解釈した) ので、削除されたが._GETurldecode()_GETurldecode()_GET

urldecode()MySQL クエリと互換性がありませんか? エンコード/デコードをバイパスするハードコードされた情報でコードをテストしたので、エンコード/デコードの問題であると確信しています。たぶん、urldecode()どうにかして文字を同じように見えるが内部的に異なる特別なものに変えているので、MySQL はそれらを読み取ることができませんか?

4

3 に答える 3

75

これをしないでください。それは間違っています。もちろん、誰でも a を使用してクエリを終了し;、新しいクエリを開始して、すべてを削除したり、ユーザーとパスワードを読み取ったりすることができます。

これを行うための簡単ではるかに優れた方法の 1 つはwww.example.com/index.php?q=hi、URL として使用し、次にサーバー上で使用することです (PHP を想定しましょう)。

$queryString = mysql_real_escape_string($_GET['q']);

$query = "AND name LIKE '%$queryString%'";

// Then replace $query for whatever you were using $_GET['q'] for before.
// Feel free to rename my variables what you like!

こうすることで、ユーザーが混乱することがなくなり、URL がきれいに見えます。mysql_real_escape_string 関数は、文字列をエスケープすることにより、クエリで安全に使用できるようにします。詳細については、 http://php.net/manual/en/function.mysql-real-escape-string.phpを参照してください。

それでもこれが有用であると確信できない場合は、誰かがあなたのテーブルを削除するリンクを公開し、Google がそれを週に 1 回クロールするとどうなるかを考えてみてください。あなたのデータは、Google がたまたま通りかかったときに削除されます。

この手法に満足したら、mod_rewrite (Apache を使用している場合) を読んで URL をさらにクリーンアップし、mysqliとそれが mysql 関数の改良版である方法、最後にクリーンアップに役立つPHP Data Objects (PDO)を読んでください。 PHPはさらにアップします。

于 2012-07-18T18:10:16.000 に答える
8

Rich は正しい一般的な考えを持っていますが、引用よりも優れているのは、データベース パラメーターを使用することです。基本的に、「変数トークン」を SQL クエリに配置し、変数を個別に渡します。クエリは次のようになります。

SELECT ID, VALUE1, VALUE2
FROM MY_TABLE
WHERE VALUE3 = :param

次に、コードで に代入する値を追加し、:paramそれを SQL と一緒にデータベースに送信します。(一部の DB ライブラリでは、:parametername の代わりに ? を使用します。) 次の 3 つの理由から、引用符で囲むよりもうまく機能します。

まず、クエリ文字列を毎回再構築するのではなく一定に保つことができるため、サーバーのパフォーマンスが向上します。

次に、複数の異なるパラメーターを使用して同じ定数クエリをデータベースに複数回送信すると、データベース エンジンはクエリ プランをキャッシュできるため、DB のパフォーマンスが向上します。

第 3 に、パラメーター化されたスタイルでクエリを記述することに慣れると、特にパラメーター リストを引数として受け取るクエリ関数を使用する場合は、それが自然になるため、間違いを犯しにくくなります。対照的に、何かを引用するのを忘れがちで、誤ってプログラムにセキュリティ ホールを開けてしまいます。

パラメータ化がどのように機能するかは、使用しているデータベースと DB アクセス ライブラリによって異なりますが、すべての SQL データベースがサポートしています。使用しているシステムでどのように行われるかを確認する必要があります。これは、特にインターネットなどの信頼できないソースからの入力がある場合に、SQL を操作するための最良の方法です。

于 2012-07-19T17:26:51.593 に答える
0

mysql_query()呼び出し後および呼び出し前のある時点mysql_fetch_array()で、クエリがfalseを返さなかったことを確認し、返された場合は出力する必要がありますmysql_error()。例えば:

$result = mysql_query($query);
if (!$result) {
   die(htmlenitites(mysql_error())." when running <pre>".htmlenitites($query)."</pre>");
}

だが:

  1. phpのmysql関数を使用するべきではなく、PDOを使用する必要があり、準備された/パラメーター化されたクエリを使用する必要があります。
  2. クライアントが入力する可能性のあるものを本当に信頼しない限り、SQLをクライアントから渡さないようにする必要があります。たとえば、これはバックエンド管理インターフェイス用であり、それでも、本当に必要でない限り、おそらく悪い習慣です( phpMySQLAdminの作成)
于 2012-07-23T09:27:09.073 に答える