【发布时间】:2016-09-10 11:47:17
【问题描述】:
我正在学习 Web 开发课程。使用 PHP PDO MySQL,他们在研讨会上教我们这样做:
function countUsers($search) {
$and = '';
if ($search != '') {
$and = " AND user_name LIKE '%".$search."%'";
}
$total = $this->db->query("SELECT COUNT(id) as rows FROM users WHERE valid = 1" . $and)->fetch(PDO::FETCH_OBJ);
return $total->rows;
}
在我看来这是完全错误的,该语句没有准备好并且直接从用户输入传递而没有任何可能导致 SQL 注入的验证,所以我向培训师提出了这个(我知道 fetchColumn() 将是在这里更合适,但为了示例,让我们坚持下去):
function countUsers($search) {
$and = '';
$sqlSearch = "%$search%";
if ($search != '') {
$and = " AND user_name LIKE :username";
}
$sql = "SELECT COUNT(id) as rows FROM users WHERE valid = 1" . $and;
$sth = $this->db->prepare($sql);
if ($search != '') {
$sth->bindParam(':username', $sqlSearch, PDO::PARAM_STR);
}
$sth->execute();
$total = $sth->fetch(PDO::FETCH_OBJ);
return $total->rows;
}
我错了吗?他们是错的还是我们都错/对了?
【问题讨论】:
-
您应该始终绑定不受信任的参数(几乎是所有参数)。
-
你完全正确。即使输入是可信的,它仍然可以包含破坏 sql 的字符,因此您应该始终使用准备好的语句并将值绑定到占位符。
-
我在课堂上提出了这个问题,他们说我是对的,但这不是问题,因为这只是一个工作示例,并不是课程的目的是拥有 20 小时的网络安全.我认为他们为学生提供完全错误和不安全的例子是非常错误的。如果不利用 PDO 的
prepared statements,他们最好使用mysql_*或mysqli_*。 -
mysqli_*也支持预处理语句:P -
真的吗? 20小时从一开始就做,也就是准备一个语句并绑定值?!看来你的老师要退休了……