我正在使用 PDO,因为它被推荐为 PHP 数据库连接的方式。但与此同时,我痴迷于保护我的查询,以确保我的系统尽可能免受黑客攻击。
PDO 和准备好的语句是一个很好的方法,但我有几个问题。我有一个自定义过滤系统,需要我手动构建查询。例如,这个:
$query=$pdo->prepare('SELECT * FROM log WHERE username=?');
$result=$query->execute(array($_GET['username']));
这行得通,一切都很好 - PDO 处理确保 $_GET 变量不会损害我的查询。
但是当我需要逃避其他事情时该怎么办?例如,如果我有这种情况,我只想返回五条记录:
$query=$pdo->prepare('SELECT * FROM log WHERE username=? LIMIT 5');
$result=$query->execute(array($_GET['username']));
这再次有效。但是如果限制值也来自 $_GET 怎么办?如何逃脱它?
为此,我首先想到我必须手动构建查询并使用 PDO::quote() 方法,如下所示:
$query='SELECT * FROM log WHERE username=? LIMIT '.$pdo->quote($_GET['limit']);
但这不起作用,因为它在限制器周围放置了引号,这会破坏查询。
有没有像 mysql_real_escape_string() 那样使用 PDO 转义的正确方法?由于后者从未在结果变量周围加上引号,但我无法使用 quote() 来阻止这种行为。
另一种选择是构建我自己的转义器,但这违背了使用 PDO 准备好的语句开头的目的(准备好的语句本身总是在值周围加上引号)。
编辑:我还尝试将值转换为引号中的整数,如下所示:
$pdo->quote((int)$value,PDO::PARAM_INT);
但它 - 仍然 - 在它周围加上引号。与 intval() 相同。
如果我必须做类似这种习惯的原始事情,为什么会如此积极地建议和推荐使用 PDO?我真的不想为这样的情况编写一个消毒方法,并希望没有任何东西被破坏或受到损害。