我有以下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查询的正确方法是什么?
答案 0 :(得分:10)
在PHP中,与许多其他编程语言一样,=
运算符assigns左侧操作数变量的右侧操作数的值。也就是说,执行这样的命令后,=
符号左侧的变量将包含=
符号右侧表达式的值。
你的右手操作数是double-quoted string literal,其中PHP用它们的值扩展(替换)变量;但是,结果(分配给左侧操作数)只是一个字符序列。
PHP的echo
构造将其参数转换为字符串(s),按顺序连接它们并将结果发送到输出缓冲区。
在你的情况下,唯一的参数是另一个双引号字符串文字"$requete"
,其中PHP再次使用它们的值扩展变量:这次文字的内容只是变量$requete
,因此引用它只会导致多余的解析开销;并且由于该变量被赋予了前一个字符串文字,因此结果字符串(由echo
输出)等于原始字符串文字。因此,您的两个陈述具有与以下相同的效果:
echo "SELECT login, pass FROM membres WHERE login='$login' AND pass='$pass'";
PHP尚未被告知存在RDBMS,这是您希望由该RDBMS评估的SQL,或者您希望输出生成的结果集。
更糟糕的是,除非您绝对确定 $login
和$pass
不包含未转义的'
字符,否则可能会导致解析该字符串的SQL意外行为。攻击者经常利用这种疏忽来执行SQL injection attacks,这可能会危及整个数据库。 最安全避免这种情况的方法是从不来评估SQL的变量,而是使用prepared statements将变量作为参数传递给它。
我建议您查看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);
然而,有些事情需要注意:
您只是从匹配常量值的数据库字段中进行选择,这是毫无意义的:从这样的查询中可以获得的唯一信息是数据库中匹配记录的数量,但是资源被浪费在返回多余的数据。
您可以改为SELECT COUNT(*) FROM membres WHERE ...
获取相同的信息,而不会浪费任何开销;或者如果您只想发现是否有一个或多个匹配记录,SELECT EXISTS (SELECT * FROM membres WHERE ...)
会更有效率。
您似乎正在创建一个登录脚本,这可以通过安全的方式完成:如果您有兴趣了解更多内容,请阅读The Definitive Guide To Forms based Website Authentication。那里有图书馆和工具,你可以直接进入你的项目,以避免浪费资源重新发明轮子(以及其他人学到的许多痛苦的错误)。