【问题标题】:Antidote for magic_quotes_gpc()?magic_quotes_gpc() 的解毒剂?
【发布时间】:2010-01-04 01:11:44
【问题描述】:

我见过几十个这样的 PHP sn-ps:

function DB_Quote($string)
{
    if (get_magic_quotes_gpc() == true)
    {
        $string = stripslashes($string);
    }

    return mysql_real_escape_string($string);
}

如果我拨打DB_Quote("the (\\) character is cool"); 会发生什么? (感谢 jspcal!)

难道我们不应该只在get_magic_quotes_gpc() == true 并且值源自$_GET$_POST$_COOKIE superglobals 时才去除斜线吗?

【问题讨论】:

  • 是的,但是没有办法跟踪一个泛型函数的值的来源。所以程序员有责任只为来自那些超全局变量的东西调用 sn-p。
  • 实际上 - 以“O'Reilly”为例 - 你会得到一个正确转义的字符串“O\'Reilly”......当你想插入一个像“O”这样的字符串时会出现问题\'Reilly"(作为稍后要显示的正确转义字符串的示例) - 因为 DB_Quote 将简单地返回 "O\'Reilly" 而不是 "O\\\'Reilly",然后从数据库中选择它会给你“O'Reilly”
  • @HorusKol:是的,你是对的。很抱歉。

标签: php stripslashes addslashes magic-quotes-gpc


【解决方案1】:

第一步是完全关闭魔术引号,并在打开时发出不可忽视的大警告。

如果这不是您的选择,那么在我看来,最好的方法是始终删除所有魔术引号。

// in an include used on every page load:
if (get_magic_quotes_gpc()) {
    foreach (array('_GET', '_POST', '_COOKIE', '_REQUEST') as $src) {
        foreach ($$src as $key => $val) {
            $$src[$key] = stripslashes($val);
        }
    }
}

对性能的影响很小,但从那时起在处理变量时会让您更加轻松。

【讨论】:

  • 同意 - 最好关闭...或更改为另一个主机
  • +1,我在所有项目中也使用类似的代码。魔术引号是迄今为止已知的 PHP 最恶毒的恶意。意图是好的,但实现是恶毒且容易出错的。禁用很好,并且在软件中(编写为在任何 PHP 事物上分发)您只需要使用此解决方法(此答案的代码,尽早执行)。
  • @nickf:$_REQUEST 怎么样,我应该也删除它还是自动反映更改?
  • 我现在已经习惯将这种 sn-p 添加到我所有的 PHP 项目中。 Magic_quotes 是一个邪恶的函数,我很高兴他们会在 PHP6 中删除它(否则我们的开发人员会做噩梦)
  • @nickf: Superglobals (like $_POST) can not be used as variable variables within functions。此代码必须在外部函数才能工作。
【解决方案2】:

是的,我也见过几十个这样的 PHP sn-ps。有点遗憾。

魔术引号是一个输入问题。它必须在输入阶段通过迭代 GET/POST/COOKIES 数组并删除斜杠来修复,如果您需要您的应用程序在服务器上运行使用古老的错误 magic_quotes_gpc。简单的替代方法是检测魔术引号选项并在设置时出现“您的服务器糟透了”错误。

mysql_real_escape_string 是一个输出问题。如果您不使用参数化查询(您绝对应该考虑),它需要在脚本退出时运行,在内容进入数据库时​​运行。

这是程序中两个独立的不相关阶段。您不能将它们放在同一个函数中,尽管尝试将所有字符串处理封装到一个盒子中可能很诱人。

难道我们不应该只在 [...] 值来自 $_GET、$_POST 或 $_COOKIE 超全局变量时去除斜杠吗?

是的,没错。这就是为什么您引用的 sn-p 确实有害的原因。因为跟踪字符串的来源是不切实际的(尤其是当您可能将来自不同来源的字符串组合在一起时,其中一个是斜线而另一个不是),您不能在一个函数中做到这一点。它必须是在适当的时候调用的两个单独的字符串处理函数。

【讨论】:

  • +1 "简单的替代方法是检测魔术引号选项,并在设置时出现“您的服务器糟透了”错误。"
【解决方案3】:

是的,正如 dav 所说,直到脚本只在表单输入上使用带斜杠...

如果你用字符串“O'Reilly”调用stripslashes,字符串不会改变。如果您使用类似以下字符串的字符串调用 stripslashes:“反斜杠 (\) 字符很酷”,则结果会将转义序列 \) 替换为 )。因此,在所有 db 值上使用该函数可能会巧妙地破坏事物,但可能不会被注意到。

像许多应用程序一样,您也可以不支持魔术引号模式。检查它并在它打开时打印错误。它已默认关闭多年,不推荐使用。

【讨论】:

  • 它确实改变了它:DB_Quote("O'Reilly") == O\'Reilly.
  • stripslashes 不会改变它,但 mysql_real_escape 会
【解决方案4】:

您可以尝试在 $_GET、$_POST 或 $_COOKIE 上执行以下操作,然后再对它们进行任何其他操作:

<?php
if (get_magic_quotes_gpc ())
{
    $_POST = array_map ('stripslashes', $_POST);
}
?>

请注意,这仅在您的输入数组是“平面”(不包含子数组)时才有效。如果您希望输入中有子数组,那么您需要编写自己的回调来处理它。类似的东西

<?php
function slashField ($input)
{
    if (is_array ($input))
    {
        foreach ($input as $key => $row)
        {
            $input [$key]   = slashField ($row);
        }
    }
    else
    {
        $input  = stripslashes ($input);
    }
    return ($input);
}

if (get_magic_quotes_gpc ())
{
    $_POST = array_map ('slashfield', $_POST);
}
?>

【讨论】:

    【解决方案5】:

    数字 6 是正确的想法但不起作用,因为直到 PHP 5.4 $$src[$key] 在 $src[$key] 上使用变量变量语法,它被解释为 $src[0],创建一个变量$_ 这是没用的。只需在 $val 和 $val = stripslashes($val) 上使用 &(引用运算符)。此外,否则从 PHP 5.4 开始,您可能会收到错误,因为 PHP 不会将 _ 强制转换为 0

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-11-10
      • 2021-03-06
      • 1970-01-01
      • 2021-01-23
      • 2016-07-28
      相关资源
      最近更新 更多