0

ユーザーのログイン情報を取得しようとする次のMySQLコマンドがあります。

$requete = "SELECT login, pass FROM membres WHERE login='$login' AND pass='$pass'";
echo ("$requete");

動いていない。問題は、このコードを実行すると、(クエリの実行結果ではなく)次の出力が表示されることです。

SELECT login, pass FROM membres WHERE login='$login' AND pass='$pass'

PHPでMySQLクエリに変数を渡す正しい方法は何ですか?

4

1 に答える 1

10

PHP では、他の多くのプログラミング言語と同様に、=演算子は右側のオペランドの値を左側のオペランド変数に代入しますつまり、そのようなコマンドが実行された後、シンボルの左側にある名前の変数には、=シンボルの右側にある式の値が含まれます=

右側のオペランドは、二重引用符で囲まれた文字列リテラルであり、PHP は変数をその値で展開 (置換) します。ただし、結果 (左側のオペランドに割り当てられる) は単なる一連の文字です。

PHP のechoコンストラクトは、そのパラメーターを文字列に変換し、それらを順番に連結して、結果を出力バッファーに送信します。

あなたの場合、唯一のパラメーターは別の二重引用符で囲まれた文字列リテラル"$requete"であり、PHP は再び変数をその値で展開します。今回は、リテラルの内容は変数のみである$requeteため、引用すると余分な解析オーバーヘッドが発生しました。その変数には前の文字列リテラルが割り当てられているため、結果の文字列 ( によって出力されるecho) は元の文字列リテラルと同じになります。したがって、2 つのステートメントは次と同じ効果があります。

echo "SELECT login, pass FROM membres WHERE login='$login' AND pass='$pass'";

PHP は、RDBMS が存在すること、これがその RDBMS によって評価されたい SQL であること、または生成された結果セットが出力されることを望んでいることを知らされていません。

さらに悪いことに、エスケープされていない文字が含まれていないことを完全に確信$loginていない限り、その文字列を SQL 用に解析すると、予期しない動作が発生する可能性があります。$pass' 多くの場合、攻撃者はこの見落としを悪用してSQL インジェクション攻撃を実行し、データベース全体を危険にさらす可能性があります。これを回避する最も安全な方法は、変数をパラメーターとして渡す準備済みステートメントを使用して、SQL の変数を決して評価しないことです。

PHP Data Objectsを調べることをお勧めします。これにより、安全なデータベース アクセスが非常に簡単になります。

$dbh = new PDO("mysql:dbname=$dbname;charset=utf8", $username, $password);
$dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);

$qry = $dbh->prepare('
  SELECT login, pass
  FROM   membres
  WHERE  login = ? AND pass = ?
');

$qry->execute(array($login, $pass));
while ($row = $qry->fetch(PDO::FETCH_ASSOC)) print_r($row);

ただし、次の点に注意してください。

  1. データベース フィールドから定数値に一致するものだけを選択しているため、これはかなり無意味です。このようなクエリから取得できる唯一の情報は、データベース内の一致するレコードの数ですが、余分なデータを返すためにリソースが浪費されます。

    SELECT COUNT(*) FROM membres WHERE ...代わりに、無駄なオーバーヘッドなしで同じ情報を取得することができます。または、一致するレコードが 1 つ以上あるかどうかのみを検出したい場合は、SELECT EXISTS (SELECT * FROM membres WHERE ...)さらに効率的です。

  2. ログイン スクリプトを作成しているようですが、これを安全な方法で実行するのは簡単ではありません。詳しく知りたい場合は、フォーム ベースの Web サイト認証の決定版ガイドをお読みください。車輪の再発明にリソースを浪費するのを避けるために、プロジェクトにドロップインできるライブラリとツールがあります (そして、他の人が苦労して学んだ多くのつらい間違いのすべて)。

于 2012-09-14T13:08:56.590 に答える