我是php/SQL的新手(1天),所以如果我用反向的方式做这件事,请原谅我。
下面的php旨在将最近的100个条目返回到DB中。我尝试通过选择要返回的100个条目并根据条目的生成日期(时间戳)进行排序来做到这一点。这将返回100个最近的条目到数据库吗?还是我理解错了?
$type = isset($_GET['type']) ? $_GET['type'] : "global";
$offset = isset($_GET['offset']) ? $_GET['offset'] : "0";
$count = isset($_GET['count']) ? $_GET['count'] : "100";
$sort = isset($_GET['sort']) ? $_GET['sort'] : "date DESC";
// Localize the GET variables
$udid = isset($_GET['udid']) ? $_GET['udid'] : "";
$name = isset($_GET['name']) ? $_GET['name'] : "";
// Protect against sql injections
$type = mysql_real_escape_string($type);
$offset = mysql_real_escape_string($offset);
$count = mysql_real_escape_string($count);
$sort = mysql_real_escape_string($sort);
$udid = mysql_real_escape_string($udid);
$name = mysql_real_escape_string($name);
// Build the sql query
$sql = "SELECT * FROM $table WHERE ";
switch($type) {
case "global":
$sql .= "1 ";
break;
case "device":
$sql .= "udid = '$udid' ";
break;
case "name":
$sql .= "name = '$name' ";
break;
}
$sql .= "ORDER BY $sort ";
$sql .= "LIMIT $offset,$count ";
$result = mysql_query($sql,$conn);
if(!$result) {
die("Error retrieving scores " . mysql_error());
}
//echo $result;
$rows = array();
while($row = mysql_fetch_assoc($result)) {
$rows[] = $row;
}
这应该可以工作,尽管date
是MySQL关键字,所以您要么需要将date
括在反引号中,要么重命名该列。
$_GET
或$_POST
构建用户可编辑值的查询是非常不安全的。对于WHERE
参数,您应该在这些参数上运行mysql_real_escape_string()
(我看到您是,我不确定您之前是否存在)。这就足够了,因为您在查询中将这些值包装在引号中,并且由于您正在转义该字符串,因此任何跳出这些引号的尝试都将不起作用。
对于像ORDER BY
这样的东西,我会定义一个允许值的有效"列表",并检查以确保您的参数在该列表中。例如:
$valid_orderbys = array('`date` DESC', '`date` ASC', '`name` DESC', '`name` ASC');
if (in_array($_GET['sort'], $valid_orderbys))
{
// you're good, you can use this value
}
else
{
// unexpected value, either alert the user or
// use a default value you define
}
或者对于LIMIT
,您可以使用PHP的内置is_numeric()
来验证您被给定的值是一个数字,而不是一个精心制作的字符串。
不足以简单地转义$table
, ORDER BY
和LIMIT
参数,因为它们没有用引号包装,因此有人可以恶意注入; DROP TABLE whatever; --
的值。这最终使您的查询类似于:
SELECT * FROM ; DROP TABLE whatever; --WHERE ...
查询以分号分隔,因此这里有三个查询。第一个失败是因为它无效,第二个成功删除了表,第三个只是一个注释,所以什么也没有发生。但你可以看到,如果你让用户输入任何他们想要的参数,这是一个大开放的安全漏洞。(我不确定是否封闭表名在反引号有助于这一点,有人让我知道,如果你知道。但是在任何情况下,您都可以对LIMIT
和ORDER BY
参数进行相同的攻击。
如果您有一个唯一的,自动增量的ID为每条记录(你应该),它将是更有效的ORDER BY id DESC
事实上,你已经做对了。您应该只考虑指定列,而不是使用*.