【问题标题】:mysql_real_escape_string() for entire $_REQUEST array, or need to loop through it?mysql_real_escape_string() 用于整个 $_REQUEST 数组,还是需要循环遍历它?
【发布时间】:2011-05-12 12:04:11
【问题描述】:

除了以下之外,还有更简单的方法可以安全地提取提交的变量吗?

if(isset($_REQUEST['kkld'])) $kkld=mysql_real_escape_string($_REQUEST['kkld']);
if(isset($_REQUEST['info'])) $info=mysql_real_escape_string($_REQUEST['info']);
if(isset($_REQUEST['freq'])) $freq=mysql_real_escape_string($_REQUEST['freq']);

(还有:你会在这种情况下使用isset() 吗?)

【问题讨论】:

  • 伙计们,我知道你们都想获得更多的声誉,但为什么没有人解释这是一个奇怪的想法呢?并且只有必要的数据应该被清理,而不是全部。
  • @zerkms,我不认为这是一个奇怪的想法,因为它在某些情况下会派上用场。但是我也同意,除了少数构成查询的数据之外,并非所有数据都应该进行清理。
  • @Starx:您不应该依赖任何神奇的方式来保护数据免受任何类型的攻击。在每种特定情况下,您都应该应用必要的功能。 IE:何时(且仅当)您需要执行 sql 查询 - 您仅将 mysql_real_escape_string() 应用于查询中使用的变量。
  • @zerkms,当您说Magic way 时,您到底指的是什么?
  • @Starx:该主题的主要思想是获得一些神奇的代码,使变量在查询中可以安全使用;-)

标签: php mysql mysql-real-escape-string


【解决方案1】:

如果你使用 mysqli 扩展并且你想转义所有 GET 变量:

$escaped_get = array_map(array($mysqli, 'real_escape_string'), $_GET);

【讨论】:

    【解决方案2】:

    要清理或验证任何INPUT_GETINPUT_POSTINPUT_COOKIEINPUT_SERVERINPUT_ENV,您可以使用

    过滤可以通过回调完成,因此您可以提供mysql_real_escape_string

    此方法不允许过滤$_REQUEST,因为you should not work with $_REQUEST 当数据在任何其他超全局变量中可用时。它可能不安全。

    该方法还要求您命名输入键,因此它不是通用的批量过滤。如果您想要通用批量过滤,请使用array_maparray_walkarray_filter,如本页其他地方所示。

    另外,你为什么使用旧的 mysql 扩展而不是 mysqli(i 表示改进)扩展。 mysqli 扩展将为您提供对transactionsmultiqueriesprepared statements 的支持(无需转义)所有可以使您的数据库代码更加可靠和安全的功能。

    【讨论】:

      【解决方案3】:

      就我而言 Starx' 和 Ryan 在 2010 年 11 月 19 日的回答是最好的解决方案,因为我也需要这个。

      当您有多个输入字段具有同一个名称(例如名称[])时,这意味着它们将被保存到 $_POST 数组中的数组中,您必须使用递归函数,因为 mysql_real_escape_string 不适用于数组。

      所以这是逃避此类 $_POST 变量的唯一解决方案。

      function sanitate($array) {
          foreach($array as $key=>$value) {
              if(is_array($value)) { sanitate($value); }
                  else { $array[$key] = mysql_real_escape_string($value); }
         }
         return $array;
      }
      sanitate($_POST);
      

      【讨论】:

        【解决方案4】:

        一次性转义所有变量:

        $escapedGet = array_map('mysql_real_escape_string', $_GET);
        

        提取所有变量到当前命名空间(即$foo = $_GET['foo']):

        extract($escapedGet);
        

        但请不要执行此最后一步。没有必要,只需将值留在数组中即可。提取变量可能导致名称冲突和覆盖现有变量,这不仅是麻烦和错误的来源,而且是安全风险。此外,正如@BoltClock 所说,坚持使用$_GET$_POST。此外2,正如@zerkms 指出的那样,mysql_real_escaping 变量中不应该在数据库查询中使用是没有意义的,它甚至可能导致进一步的问题。


        请注意,实际上没有这不是一个特别好的主意,您只是在重生 magic_quotes 和 global_vars,它们是过去很长时间以来可怕的 PHP 实践。通过 mysqli 或 PDO 使用带有绑定参数的预处理语句,并通过 $_GETfilter_input 使用值。见http://www.phptherightway.com

        【讨论】:

        • @ajo 数据本身从不危险,正是您使用它的上下文可能使其变得危险。 mysql_real_escape 仅在 SQL 查询中使用数据时保护您。如果您不在 SQL 查询中使用数据,它将(可能)仅更改数据,它不会或多或少地保存它。如果您将数据回显到 HTML 页面中,mysql_real_escaping 将无济于事,您需要改用htmlentities...上下文很重要!
        • 嗯,在他删除之前,我正在回复这条 ajo 的评论......无论如何我都会在这里留下我的评论。
        • 我知道现在每个人都应该使用PDOprepared statements,但是当$_REQUEST 或$_POST 变量是array 时,这不会失败吗?例如,当提交多个具有相同名称的复选框值时
        • @wired00 是的,当然。这种大规模的逃避实际上从来都不是一个好主意,但在 OP 的有限情况下,它是有目的的。仅当您知道自己在做什么时才应该应用它(一如既往)。
        • 很酷,感谢您的澄清。是的,我认为在 OP 案例中它很好,因为无论如何他都在使用$_GET。只是想确认我自己的情况。我们有大量遗留代码无法转换为PDO,因此必须使用mysqli_real_escape_string()
        【解决方案5】:

        您也可以使用这样的递归函数来完成此操作

        function sanitate($array) {
           foreach($array as $key=>$value) {
              if(is_array($value)) { sanitate($value); }
              else { $array[$key] = mysql_real_escape_string($value); }
           }
           return $array;
        }
        sanitate($_POST);
        

        【讨论】:

          【解决方案6】:

          作为替代方案,我可以建议您使用PHP7 input filters,它提供了 sql 转义的快捷方式。我不推荐它本身,但它可以避免创建本地化变量:

           $_REQUEST->sql['kkld']
          

          可以在 SQL 查询字符串中内联使用,如果您忘记它,请提供额外的警告:

           mysql_query("SELECT x FROM y WHERE z = '{$_REQUEST->sql['kkld']}'");
          

          它在语法上是有问题的,但只允许您转义那些真正需要它的变量。或者模仿你的要求,使用$_REQUEST->sql->always();

          【讨论】:

            猜你喜欢
            • 2020-10-09
            • 1970-01-01
            • 1970-01-01
            • 2021-09-30
            • 2017-05-14
            • 2019-07-10
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多