我目前正在寻找使用API安全地连接和管理查询(SQL注入缓解)的方法,同时尝试遵循DRY指南。我使用准备好的语句来防止SQL注入,但是在运行接收到HTTP GET请求时调用的函数时,我遇到了警告:
警告:mysqli::bind_param():变量的数量不匹配参数的数量在准备语句…
然后我的查询失败:
错误:command out of sync;你现在不能运行这个命令Errno 2014
一个简单的谷歌搜索给了我这个答案:
如果你得到命令不同步;你现在不能在你的客户端代码中运行这个命令,你调用客户端函数的顺序错了。
警告和错误消息仅在数组中有多个参数时发生。我的mySQL查询函数如下:
//set properties to values given by constructor params,
//open mysqli connection, etc..
public function query_db_stmt($sql, $param)
{
$stmt = $this->connection->prepare($sql);
for ($i = 1; $i < count($param); ++$i)
{
$stmt->bind_param(($param[0][$i - 1]), $param[$i]);
}
$stmt->execute();
$result = $stmt->get_result();
$stmt->close();
return $result;
} // do other stuff here, like close the sql connection in __destruct()...
然后创建对象,然后像这样调用查询函数:
$sql = 'SELECT ? FROM user WHERE id=?;';
$result = $mysql_db->query_db_stmt($sql, array('si', '*', $this->args[0]));
我显然做错了什么,因为我得到这些警告,和一个错误的数字2014,但我不知道它是什么。如有任何帮助,不胜感激。
编辑:
我现在明白我不能使用列名或表名作为预处理语句,但是在使用此代码时,除了HTTP PUT请求之外,我仍然有类似的问题:
parse_str(file_get_contents("php://input"), $put_vars);
$sql = 'INSERT INTO user (username, password, email, birth, sex) VALUES (?, ?, ?, ?, ?);';
$mysql_db->query_db_stmt($sql, array('sssss', $put_vars['username'], password_hash($put_vars['password'], PASSWORD_DEFAULT),
$put_vars['email'], $put_vars['birth'], $put_vars['sex']));
使用curl,我运行curl -X PUT http://localhost/r.php -d username=foo -d password=boo -d email=test@gmail.com -d birthday=2015-08-13 -d sex=m
我得到相同的错误5次:
警告:mysqli::bind_param():变量的数量不匹配参数的数量在准备语句…
如前所述,But no DB Query failed错误。任何评论?
问题是您试图在PDO中绑定表名。PDO中不能替换表名和列名
您不需要将列名放在?
中并准备语句。相反,只需将语句的值作为参数并将变量绑定到它们。所以$sql
应该是-
$sql = 'SELECT * FROM user WHERE id=?';
然后相应地绑定变量。
另外,不要在查询中使用SELECT *
,总是指定您想要输出的列名。