【问题标题】:php beginner safe input [duplicate]php初学者安全输入[重复]
【发布时间】:2011-03-15 22:44:35
【问题描述】:

可能重复:
mysql_fetch_array() expects parameter 1 to be resource, boolean given in select

我需要一些帮助。

我有这个问题:

$order = isset($_GET['order']) ? mysql_real_escape_string($_GET['order']) : 'title';
$query = mysql_query("SELECT * FROM entry ORDER BY $order ASC");

您可以按标题、日期或作者排序。

但如果有人给 $order 其他东西,它会继续:

Warning: mysql_fetch_assoc() expects parameter 1 to be resource, boolean given in C:\wamp\www\entries.php on line 20

如何消除此错误消息?

谢谢

【问题讨论】:

    标签: php


    【解决方案1】:

    您不能在 order by 子句中使用 colu\'nname 之类的东西——这意味着 mysql_real_escape_string 不是这里的解决方案。

    相反,您应该检查 $order 是否确实包含表中某一列的名称,如果不包含则不要运行查询。


    例如,你可以使用这样的东西:

    if (!in_array($_GET['order'], array('column1', 'title', 'id', 'other_column'))) {
        // deal with the problem
        // and don't run the query
        // because $_GET['order'] is not one of the allowed values
    }
    

    【讨论】:

      【解决方案2】:

      您不应将列标识符视为字符串文字。在您的示例中,您最终可能会得到这样的 SQL:

      SELECT * FROM entry ORDER BY O\'Hare ASC
      

      这会导致任何 SQL 解析器出现语法错误。

      我有几点建议:

      1. 将您的 SQL 放入一个变量中,不要尝试在对 mysql_query() 的调用中构建它。如果使用变量,现在可以检查 SQL 字符串,这样更容易发现上述错误。

        $sql = "SELECT * FROM entry ORDER BY $order ASC";
        // here you can log $sql, or output to Firebug, etc.
        $query = mysql_query($sql);
        
      2. 检查返回值是否表示错误。您需要检查错误状态,因为它们发生的原因有很多。

        $query = mysql_query($sql);
        if ($query === false) {
          die(mysql_error());
        }
        
      3. mysql_real_escape_string() 用于字符串——而不是列名、表名、SQL 关键字等。我使用的是关联数组,它将$_GET 输入映射到有效的列名,所以我知道它是安全的。这还允许您在应用参数中使用与列名称不同的值。

        $ordercolumns = array(
          "t" => "title",
          "d" => "date"
        );
        $order = "title"; // the default
        if (isset($_GET["order"]) && isset($ordercolumns[$_GET["order"]])) {
          $order = $ordercolumns[$_GET["order"]];
        }
        // now we know $order can only be 'title' or 'date', 
        // so there's no need to escape it.
        $sql = "SELECT * FROM entry ORDER BY $order ASC";
        

      【讨论】:

      • 很好的答案!我学到了一些新东西:)我会收藏这个;P
      【解决方案3】:

      只是不向用户提供任何订单选项,事实并非如此。如果您使用的是文本输入,请将其替换为选择。只要该列存在,就不会出现错误。

      您可以在 switch-case 中对每个选项进行硬编码:

      switch($_GET['order']){
          case 'date' : 
               $order = 'date';
               break;
          case 'author' : 
               $order = 'author';
               break;
          default
               $order = 'title';
      }
      

      这也将防止 SQL 注入。

      【讨论】:

        【解决方案4】:

        它需要 $order 中的列名,如果不是,它将失败。尝试回显 $query。

        【讨论】:

          【解决方案5】:

          您应该从可能的可接受值列表中检查 $_GET['order'] 的值。

          在尝试获取行之前,您还应该检查 if ($query) 以确定查询是否有效。

          【讨论】:

            【解决方案6】:
            $checker = array('title', 'date', 'author')
            
            $order = isset($_GET['order']) ? mysql_real_escape_string($_GET['order']) : 'title';
            
            if (in_array($_GET['order'], $checker) {
              $query = mysql_query("SELECT * FROM entry ORDER BY $order ASC");
            }
            

            【讨论】:

              【解决方案7】:

              您应该检查有效值,如果不符合您的预期,则向用户显示错误。

              一个简单的例子,

              $valid_values = array("title", "date", "author");
              
              if (in_array($_GET['order'], $valid_values))
              {
                  // Your db stuff
              }
              else
              {
                  echo "The order value you gave wasn't valid. Please try another.";
              }
              

              【讨论】:

                【解决方案8】:

                您还需要确保$_GET["order"] 包含有效的列。
                您的问题来自于您在查询中输入的无效列名。 mysql_query() 函数在错误时返回 false,并且您的错误消息告诉您将它传递给 mysql_fetch_assoc 调用。

                试试类似的东西

                $columns = array("id", "name", "title");
                if (false === ($key = array_search($_GET["column"], $columns))) {
                  $column = "title";
                } else {
                  $column = $columns[$key];
                }
                $query = "SELECT * FROM entry ORDER BY {$column};";
                

                我没有使用mysql_real_escape_string,因为此方法还会检查输入是否在有效选项列表中。

                【讨论】:

                  【解决方案9】:

                  在运行查询之前检查 $order 是一个列名

                  $order = isset($_GET['order']) ? mysql_real_escape_string($_GET['order']) : 'title';
                  //Run a check here, before the query
                  $query = mysql_query("SELECT * FROM entry ORDER BY $order ASC");
                  

                  mysql_real_escape_string 看起来也位于不正确的位置。提醒一下

                  【讨论】:

                  • 此代码不检查列名是否有效...
                  • 我只是向 OP 展示了在哪里进行检查。在设置 var 之后和尝试查询之前...
                  猜你喜欢
                  • 2012-09-04
                  • 2017-08-20
                  • 2015-09-27
                  • 2015-02-11
                  • 2019-05-30
                  • 2022-10-15
                  • 2019-10-21
                  • 1970-01-01
                  • 2013-07-04
                  相关资源
                  最近更新 更多