【问题标题】:Getting the 100 most recent DB entries from SQL DB via PHP通过 PHP 从 SQL DB 获取 100 个最新的 DB 条目
【发布时间】:2011-04-16 04:02:54
【问题描述】:

我对 php/SQL 很陌生(1 天),所以如果我以向后的方式这样做,请原谅我。

下面的这个 php 旨在将 100 个最近的条目返回到数据库中。我尝试通过选择要返回的 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;
}

【问题讨论】:

    标签: php mysql sql


    【解决方案1】:

    这应该可以工作,尽管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() 来验证您得到的值是一个数字,而不是一个精心设计的字符串。

    不够简单地转义 $tableORDER BYLIMIT 参数,因为它们没有用引号括起来,因此有人可以恶意注入 ; DROP TABLE whatever; -- 的值.这最终使您的查询类似于:

    SELECT * FROM ; DROP TABLE whatever; --WHERE ...
    

    查询用分号隔开,所以这里有三个查询。第一个失败是因为它无效,第二个成功删除了表,第三个只是一个注释,所以什么也没有发生。但是你可以看到,如果你让用户随意抛出他们想要的任何参数作为这些参数之一,这是一个敞开的安全漏洞。 (我不确定将表名括在反引号中是否有帮助,如果您知道,请告诉我。但无论如何,您可以对LIMITORDER BY 参数进行相同的攻击。)

    【讨论】:

    • 这可能是我的绿色表现,但你所说的“净化这些输入”是什么意思你能给我举个例子来说明什么是“净化”吗?
    • 我扩展了我的答案,看看吧。如果您还有其他问题,请告诉我。 :)
    【解决方案2】:

    如果您对每条记录都有一个唯一的、自动递增的 ID(您应该这样做),那么ORDER BY id DESC 会更有效。

    【讨论】:

    • ORDER BY id DESC 会给我最近添加到数据库的 100 个还是前 100 个?
    • @Code: ORDER BY id ASC 会给你前 100 个。
    【解决方案3】:

    实际上,您已经做对了。您应该只考虑指定列而不是使用 *。

    【讨论】:

    • 为了简洁起见,你想列出你需要的所有列,而不是偷懒做*
    • 呃,错误的数据库。我的错。而 * 是因为 OP 没有包含有问题的列。我编辑了帖子以使其更加合规。
    猜你喜欢
    • 1970-01-01
    • 2017-02-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多