作为一个新手,我已经按照PHP MySQL教程建议使用常规的MySQL php函数。但是,由于我被告知PDO是更好的选择,我一直在将我的代码转换为。我刚遇到以下问题:
$query = $uspdb->prepare("SELECT post_id, is_approved, reports FROM ? WHERE id=? AND ?");
$query->bindValue(1, $table, PDO::PARAM_INT);
$query->bindValue(2, $id, PDO::PARAM_INT);
$query->bindValue(3, checkPermission("comment_moderation"),PDO::PARAM_BOOL);
$query->execute;
$result = $query->fetch(PDO::FETCH_ASSOC);
第一行抛出以下PDO异常:
SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '? WHERE id=? AND ?' at line 1
为什么?我不知道语法有什么问题。 tutorial I'm reading告诉我,我应该使用bindValue或execute(array(stuff))来添加参数而不是“。$ id”。和喜欢,因为它更安全,但这无论出于何种原因都不起作用。
答案 0 :(得分:1)
不幸的是,预准备语句只能表示数据文字。 (在模拟准备的情况下)。 因此,开发人员必须自己处理标识符 - PDO为此事提供无帮助。
要使动态标识符安全,必须遵循2条严格的规则:
格式化后,可以安全地将$ table变量插入到查询中。所以,代码将是:
$field = "`".str_replace("`","``",$field)."`";
$sql = "SELECT * FROM t ORDER BY $field";
然而,虽然这样的格式对于像ORDER BY这样的情况就足够了,但对于大多数其他情况,有可能进行不同类型的注入:让用户选择他们可以看到的表或字段,我们可能会泄露一些敏感信息,如密码或其他个人数据。因此,最好根据允许值列表检查动态标识符。这是一个简短的例子:
$allowed = array("name","price","qty");
$key = array_search($_GET['field'], $allowed));
if ($key === false) {
throw new Exception('Wrong field name');
}
$field = $allowed[$key];
$query = "SELECT $field FROM t"; //value is safe
答案 1 :(得分:0)
通常情况下,我在提出问题后几秒钟解决了我的问题。
问题是您只能绑定这样的键值,而不能绑定表名或列名。我必须像以前一样手动插入表名和列名:
$query = $uspdb->prepare("SELECT post_id, is_approved, reports FROM $table WHERE id=? AND ?");
$query->execute(array($id,checkPermission("comment_moderation")));
$result = $query->fetch(PDO::FETCH_ASSOC);
如果表或列名由用户自行决定,您应该执行其他步骤来清理它,这在上面的您的常识的响应中有详细说明。在我的例子中,它是以下代码:
$type = $_GET[type];
switch($type) {
case "review":
$table = "site_cmt_reviews";
break;
default:
$table = "site_cmt_articles";
}
仍然,感谢阅读!