mysql_real_escape_string()对整个$_REQUEST数组使用还是需要循环处理?

3

除了以下方法,是否有更简单安全的提取提交变量的方式?

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()吗?)

2
各位,我知道你们都想要获得更多的声望,但为什么没有人解释这是一个非常奇怪的想法呢?只有必要的数据应该被清理,而不是全部清理。 - zerkms
@zerkms,我不认为这是一个奇怪的想法,因为在某些情况下它可能会很方便。然而,我也同意并非所有数据都应该被消毒,除了那些构成查询的少数数据。 - Starx
2
@Starx:你不应该依赖任何神奇的方式来保护数据免受任何形式的攻击。在每种特定情况下,你都应该应用必要的函数。例如:当(且仅当)你需要执行 SQL 查询时,只需对查询中使用的变量应用 mysql_real_escape_string() 函数即可。 - zerkms
@zerkms,当你说“Magic way”时,你具体是指什么? - Starx
2
@Starx:该主题的主要想法是获取一些神奇的代码,使变量在查询中使用更加安全。;-) - zerkms
6个回答

31

一次性转义所有变量:

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

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

extract($escapedGet);
请不要进行最后一步操作。没有必要这样做,只需要将值留在一个数组中即可。提取变量可能会导致名称冲突和现有变量的覆盖,这不仅是麻烦和错误来源,而且还存在安全风险。此外,正如@BoltClock所说,请坚持使用$_GET$_POST。另外,正如@zerkms指出的那样,对于不应在数据库查询中使用的变量,没有必要进行mysql_real_escape_string转义,这甚至可能导致进一步的问题。

请注意,所有这些都不是特别好的想法,您只是在重复使用以前可怕的 PHP 做法——magic_quotes 和 global_vars。请使用 mysqli 或 PDO 中的预处理语句和绑定参数,并通过 $_GETfilter_input 使用值。请参见http://www.phptherightway.com


1
@ajo 数据本身并不危险,而是你使用它的上下文可能会使其变得危险。mysql_real_escape仅在使用数据进行SQL查询时才能保护您。如果您没有在SQL查询中使用数据,则它只会(可能)更改数据,而不会使其更加安全或不安全。如果您将数据回显到HTML页面中,则对其进行mysql_real_escaping处理无济于事,您需要使用htmlentities代替... 上下文很重要! - deceze
好的,我之前正在回复ajo的评论,但他已经删除了它...不过我还是会把我的评论留在这里。 - deceze
1
我知道现在每个人都应该使用PDOprepared statements,但是当$_REQUEST$_POST变量是一个array时,这种方法不会失效吗?例如,当提交具有相同名称的多个复选框值时。 - wired00
@你 哦,当然可以。 :) - deceze
如果您要在查询中使用get或post参数的键,则这些键也需要进行转义!让我们不要忘记! - e-motiv
显示剩余5条评论

4
你可以使用递归函数来实现这个功能,例如:
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);

1

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

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

此方法不允许为$_REQUEST进行过滤,因为当数据在其他超级全局变量中可用时,您不应该使用$_REQUEST。这可能存在安全隐患。

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

另外,为什么你在使用旧的mysql扩展而不是mysqli(i代表改进)扩展呢?mysqli扩展将为您提供事务多查询预处理语句(消除了转义的需要)等支持。所有这些功能都可以使您的数据库代码更加可靠和安全。

0

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

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

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

当您有多个具有一个名称的输入字段(例如names [])时,这意味着它们将保存在$ _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);

-2
作为另一种选择,我可以建议您使用PHP7输入过滤器,它提供了一种快捷的方法来进行SQL转义。我不会特别推荐它,但它可以避免创建本地化变量:
 $_REQUEST->sql['kkld']

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

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

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接