这是代码吗
class opinion
{
private $dbh;
var $opinionid,$opinion,$note,$actorid,$dateposted;
var $isnew=FALSE;
function loadby($column,$value,$operator="="){
$dbh = new PDO(I deleted parameters here);
$statement=$dbh->prepare("select * from fe_opinion where :column :operator :value");
$statement->bindParam(":column", $column);
$statement->bindParam(":value", $value);
$statement->bindParam(":operator", $operator); //UNSURE, DOUBTFUL
$statement->bindColumn("opinionid", $this->opinionid);
$statement->bindColumn("opinion", $this->opinion);
$statement->bindColumn("note", $this->note);
$statement->bindColumn("actorid", $this->actorid);
$statement->bindColumn("dateposted", $this->dateposted);
$statement->fetch();
return $statement->rowCount(); //please be 1
}
}
注射安全吗?
$statement->bindParam(":operator", $operator); //UNSURE, DOUBTFUL
我可以将参数绑定到PDO语句作为比较运算符吗?
答案 0 :(得分:2)
不,你不能绑定那样的运营商。作为一种变通方法,您可以动态创建“基本”SQL查询并使用运算符白名单(这是非常合适的)来保持注入安全:
function loadby($column,$value,$operator="="){
$dbh = new PDO(...);
$operator = getOperator($operator);
if(!$operator) {
// error handling
}
$statement=$dbh->prepare("select * from fe_opinion where :column $operator :value");
// the rest like you already do it
}
function getOperator($operator) {
$allowed_ops = array('=', '<', '>'); // etc
return in_array($operator, $allowed_ops) ? $operator : false;
}
除此之外,其余的都很好,并且“按照定义”注射防护。
答案 1 :(得分:0)
如评论中所述,我认为不可能逃脱运营商并使其按预期工作。生成的查询可能类似于:
'column' '=' 'value';
您不需要逃避操作员以避免注入攻击,您可以在将操作员附加到字符串之前验证您的操作员,请考虑:
class opinion
{
$validOperators = array('=', '>=', '>', '=<', '<');
function loadby($column,$value,$operator="=") {
// Validate operator
if (!in_array($operator, self::$validOperators)) {
throw new Exception('Invalid $operator ' . $operator . ')';
}
$statement=$dbh->prepare("select * from fe_opinion where :column " . $operator . " :value");
}
}
答案 2 :(得分:0)
根据DBMS和PHP驱动程序,预准备语句可以是“真实的”或模拟的。
在第一种情况下,绑定参数由DBMS直接处理。在这种情况下,将操作符作为参数处理可能会触发语法错误。 SQL解析器将在不查看参数的情况下分析查询,并且无法找到有效的SQL代码。
在第二种情况下,绑定参数由驱动程序模拟:输入值插入到SQL代码中(具有足够的转义),DBMS接收完整的常规查询。我不确定当前的驱动程序将如何表现(我需要测试它),但即使他们不抱怨无效的SQL,它们迟早会碰壁:SQL运算符不是字符串。< / p>
现在,某天能够实施它会是一个很好的功能吗?我怀疑是:
答案 3 :(得分:-2)
你实际上可以做到。 sql变得更加复杂。根据组合的数量,sql可以变得非常庞大。但是,有时当只有少数选择时,它很好。
select *
from someTable
where (case :column
when 'age' then (case :operator
when '>' then age > :value
when '<' then age < :value
end)
when 'price' then (case :operator
when '>' then price > :value
when '<' then price < :value
end)
end)
and someOtherCol = 'foo'
:值也可能是另一个列,但是您需要再次嵌套另一个案例构造,就像第一列一样,并且组合现在真的在飙升。
无论如何......只是想表明它可以完成。