【问题标题】:Confusion about mysql_real_escape_string and strip_slashes关于 mysql_real_escape_string 和 strip_slashes 的困惑
【发布时间】:2012-03-06 09:13:31
【问题描述】:

我让用户输入他们的姓名,例如:O'riley

在将此数据输入 MySQL 数据库之前,我运行 mysql_real_escape_string

问题是,当我选择此数据以供稍后显示和使用时,它会显示为:O\'riley

显然,这是预期的操作。我想知道是否有某种方式可以确保我可以将它存储在数据库中(仍然安全地逃避可能的恶意代码),这样我每次调用数据时都不必在输出上使用strip_slashes()整个网络应用程序?或者,我在这里遗漏了什么?

谢谢。

更新 请参考 Deceze 回答中的 cmets。

【问题讨论】:

  • 你能从你的php.ini 中显示魔术引号sn-p 吗?

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


【解决方案1】:

不,将字符串存储为“O\'riley”不是预期的操作;它应该只在查询中转义,但不能以这种方式存储。我猜 PHP 通过Magic Quotes 加入反斜杠,然后你再次转义它以使其粘住。

Disable Magic Quotes.

【讨论】:

  • 这很奇怪。在php.ini 中肯定是关闭的 - 在 WHM 中显示相同。然而,phpinfo() 显示为 ON。我已经直接在Configuration File (php.ini) Path: /usr/local/lib 中编辑了 PHP.ini - 但它仍然显示为 ON。以前不是这样的,有什么想法吗??
  • CLI、Apache等场景使用的.ini可能不同。检查phpinfo()它正在使用哪个ini。
  • 似乎是那个目录中的同一个...Loaded Configuration File /usr/local/lib/php.ini 我已经验证这确实是关闭的。我在 HTACCESS 中将其设置为关闭,现在它在 php info(本地)中显示为关闭,但在(主值)中显示为 ON(主值)......这很奇怪。此外,它似乎仍然无法解决问题......并且它们被插入到带有斜杠的数据库中。
  • 然后做一些调试。在什么时候添加斜线?它已经在 POST 数据中了吗?查询到底是什么样的?您是否尝试按照 PHP.net 上关于动态删除魔术引号斜杠的说明进行操作?
  • 嗯,你试过php.net/manual/en/security.magicquotes.disabling.php的代码sn-p吗?
【解决方案2】:

我个人总是关闭魔术引号,因为它正在做我没有告诉它做的事情。如果您无法将其关闭,请考虑将此代码包含在所有页面的顶部。

if (get_magic_quotes_gpc()) {
    function strip_array($var) {
        return is_array($var)? array_map("strip_array", $var):stripslashes($var);
    }

    $_POST = strip_array($_POST);
    $_SESSION = strip_array($_SESSION);
    $_GET = strip_array($_GET);
}

【讨论】:

  • 要扩展@VIPINJAIN 评论,如果你做了这样的事情,那么以后想要为mysql 保护一个帖子,将会涉及到额外的斜线。例如,运行<?php $test = strip_slashes("Some ' quote"); echo mysql_real_escape_string(); ?> 您将转义引号和转义反斜杠。从数据库中提取将有一个额外的反斜杠。
【解决方案3】:

如果您禁用了魔术引号,并且在 get_magic_quotes_gpc 返回 1 并且您执行了类似 @Michael 显示的操作并且此仍然发生的情况下,可能会启用魔术引号运行时。

在进行数据库查询甚至写入文件时,魔术引号运行时会在字符串中添加斜杠。要在当前执行的脚本中禁用此功能,请执行以下操作:

if(function_exists('get_magic_quotes_runtime') && get_magic_quotes_runtime())
{
    set_magic_quotes_runtime(false);
}

如果可以的话,您也可以禁用此configuration option through php.ini。但是,如果您不能通过php.ini 永久禁用它,您可能需要在get_magic_quotes_runtimeset_magic_quotes_runtime 之前添加@,因为如果error_reporting 设置为记录此类错误,PHP 可能会通过E_DEPRECATED 错误(这将得到相当烦人)。

【讨论】:

    【解决方案4】:

    好的,这是你需要做的。一、基于cmets,来自其他问题:

    隔离

    您需要确定导致问题的原因。是服务器吗?是某处隐藏的代码吗?什么?一些程序员可能会在配置页面中包含这样的代码:

    <?php if (isset($_POST)) 
        foreach ($_POST as $key => $value) $_POST[$key] = addslashes($value); 
    ?>
    

    所以这里有一些检查,看看它是否是服务器。这是一种尽可能可靠的检查方式。创建一个页面。将其完全留空并添加以下代码:

    <?php print_r($_POST); ?>
    <form action="" method="POST">
    <input type="text" name="test" value="O'riley" />
    <input type="submit" name="submit" value="submit" />
    </form>
    

    保存并在浏览器中加载。点击提交。查看斜线是否仍然添加。

    如果仍在添加,则需要对服务器/配置进行故障排除。如果它是您支付的服务器,您需要告诉他们修复它或推动它。如果它是您自己的服务器,那么您将需要做一些混乱/谷歌搜索来弄清楚如何关闭魔术引号。

    如果没有出现引号,那么肯定有一些代码在您的帖子变量中添加了斜杠。但是,它可能不像上面的代码那么明显。您需要在您的代码中搜索“addslashes”、“mysql_real_escape_string”,可能还有“str_replace”。如果您发现其中之一,则需要禁用它。但请注意,这可能会破坏您网站的其他假设此操作正在发生的部分。您将其存储在数据库中的另一个选择是执行类似于上面代码的功能,但改为在其上运行 stripslashes。然后您可以稍后在其上运行 mysql_real_escape_string。 (更多不必要的开销。)

    【讨论】:

      【解决方案5】:

      使用

      var_dump(get_magic_quotes_gpc());
      

      在接近实际使用发布数据的地方查看魔术行情是否真的关闭。

      此外,一些奇怪的框架可能会为您添加上述引号,因此请使用您的代码为 addslashes 和其他类似 escape_string 的函数添加代码。

      【讨论】:

      • 好的...所以这返回 false...。现在给我一个小时的时间跑回去。这让我大吃一惊!
      • 给出更准确的答案
      【解决方案6】:

      我真诚地建议使用 PDO。

      PDO 使用准备和执行语句,这反过来又增加了安全性并消除了一些额外的麻烦。

      $pdo = new PDO();
      $stm = $pdo->prepare('INSERT... (LastName) VALUES (:LastName)');
      $stm->execute(array(':LastName' => "O'Rily"));
      
      $stm->fetchAssoc(PDO::FETCH_ASSOC);
      

      您不再需要担心删除转义斜线以及保护基本的 sql 注入策略。

      【讨论】:

      • 我很乐意,但这是一个旧代码库。尝试更换所有东西会很疯狂。
      • 您可以做的一个想法是半覆盖现有的 MySQL 函数,例如... $result = my_mysql_query($mysql_resource, 'INSERT INTO ...'); $row = my_mysql_fetch_assoc($result); function my_mysql_query($mysql_resource, $query){ return mysql_query($mysql_resource, mysql_real_escape_string($query, $mysql_resource)); } function my_mysql_fetch_assoc($resource){ $result = mysql_fetch_assoc($resource); return array_map("strip_slashes", $result); }
      【解决方案7】:

      可能在您的 httpd.conf 或虚拟主机声明中启用了魔术引号。

      确切的位置和文件取决于操作系统和发行版。我会检查 Apache 配置文件中的 php_flag 设置。

      【讨论】:

      • php_flag magic_quotes_gpc On 也可以在 .htaccess 文件中设置。
      【解决方案8】:

      只需在插入数据库之前使用清理数据,

      function check_input($value)
      {
          if( get_magic_quotes_gpc() )
          {
              $value = stripslashes( $value );
          }
      
          //check if this function exists
          if( function_exists( "mysql_real_escape_string" ) )
          {
              $value = mysql_real_escape_string( $value );
          }
      
          //for PHP version < 4.3.0 use addslashes
          else
          {
              $value = addslashes( $value );
          }
      
          return $value;
      }
      
      
      $cleandata = check_input($value);
      
      $sql = "INSERT INTO `table_name` SET `field_name`='".$cleandata."'";
      

      在获取数据并显示到其中时,使用stripslashes($val)

      【讨论】:

        【解决方案9】:

        谢谢大家的回答。我会奖励+50,但我想在这里告诉我真正的解决方案,所有这些人都提供了帮助......

        我在所有数据发布后(在任何处理之前)立即对所有数据执行mysql_real_escape_string。因此,添加了一个斜杠来转义提交的' 字符。我们知道这是正常的。

        但是,反斜杠 \ 没有理由出现在 DB 条目中,对吧?转义是为了确保输入了'

        事实证明,在转义之后,我会保存要在会话中重新加载到页面的变量,以防用户在验证所有表单字段时遇到 PHP 发现的错误。在这种情况下,用户的输入(以前的 O'riley 现在以 O\'riley 打印到他们的屏幕上。然后,用户没有注意到这一点 - 所以他们通常会修复 PHP 在验证期间捕获的错误(与name 字段),因此O\'riley 将进入数据库,因为mysql_real_escape_string 会转义字符。

        课程: 处理表格时,首先保存数据以供表格重新填写使用。第二次验证表单字段。第三个转义数据以处理到数据库中。

        或者更好的是,使用 PDO 并避免这种情况 =)。

        欢迎评论。谢谢大家!

        【讨论】:

        • 您的方法存在一个严重错误。不需要转义任何“数据”,只需要转义 SQL 字符串。对于所有其他数据类型,转义是无用的,因此会使您对注入敞开大门。
        • @YourCommonSense 我看不懂评论?
        猜你喜欢
        • 2014-10-30
        • 2011-12-13
        • 2017-12-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-05-17
        • 2020-03-06
        • 2016-03-16
        相关资源
        最近更新 更多