使清理函数遍历潜在的嵌套数组

问题描述 投票:0回答:7

我在 PHP 表单处理程序中有以下代码块:

function filter($data) {
    $data = trim(htmlentities(strip_tags($data)));
    
    if (get_magic_quotes_gpc()) {
        $data = stripslashes($data);
    }
    $data = mysql_real_escape_string($data);
    
    return $data;
}

foreach($_POST as $key => $value) {
    $data[$key] = filter($value);
}

我正在修改我的表单,现在包括复选框组:

例如:

<input type="checkbox" name="phone_prefs[]" value="prefer_home">
<input type="checkbox" name="phone_prefs[]" value="prefer_cell">
<input type="checkbox" name="phone_prefs[]" value="prefer_work">
etc.

由于这段代码,我现在的 _POST 变量中有数组,而不仅仅是字符串。

我认为我的

filter()
函数实际上不会正确清理数组,这是正确的吗?我需要对我的
filter()
函数进行哪些更改,以确保复选框的数组得到彻底清理,而不是成为 SQL 注入攻击的简单目标?

php arrays recursion post sanitization
7个回答
4
投票

对于sql注入,我会使用prepared语句切换到PDO。

您可以在值上使用简单的

is_array()
来检查数组,然后循环遍历它。你是对的,事实上,你的
filter
函数将无法正确处理数组。

编辑:如果您使用 PDO 和准备好的语句,则不再需要

mysql_real_escape_string
strip_tags
htmlentities
trim
也不需要将信息安全地存储在数据库中,当您将信息输出到浏览器时需要它们(
trim
当然不是......),尽管
htmlspecialchars
就足够了。为当时要输出到的媒体正确准备信息/输出总是更好。


2
投票

你的函数非常好,但是如果你让它递归,它会为你抓取嵌套数组

function filter(&$array) {
    $clean = array();
    foreach($array as $key => &$value ) {
        if( is_array($value) ) {
            filter($value);
        } else {
            $value = trim(strip_tags($value));
            if (get_magic_quotes_gpc()) {
                $data = stripslashes($value);
            }
            $data = mysql_real_escape_string($value);
        }
    }
}

filter($_POST); # filters $_POST and any nested arrays by reference

编辑:省略

htmlentities()
。如果您需要它,请在输出值时使用它,而不是在将它们作为输入时使用。


2
投票
array_walk_recursive($array,function(&$item){
     $item=mysql_real_escape_string($item);
});  

1
投票

您在 $_POST 上使用了 foreach,它只循环一次,使用数组并将其像字符串一样处理。

尝试使用:

foreach($_POST['phone_prefs'] as $key => $value)

编辑:

我相信我误解了你的问题:

foreach($_POST as $key => $value)
    if (is_array($value))
        foreach($_POST[$key] as $key2 => $value2)
            /* Setting stuff */
    else /* Setting same stuff */

1
投票

不要手动清理输入,而是使用 always prepared statementsplaceholders。这将以不需要转义的方式透明地将输入传递到数据库,因此不易受到 SQL 注入的攻击。这是目前最好的做法。

有关更多信息,请参阅以下内容:http://php.net/manual/en/pdo.prepared-statements.php


1
投票

我在我创建的各种网站上使用它:

public function clean($dirty) {
    if (!is_array($dirty)) {
        $dirty  = ereg_replace("[\'\")(;|`,<>]", "", $dirty);
        $dirty  = mysql_real_escape_string(trim($dirty));
        $clean  = stripslashes($dirty);
        return $clean;
    }
    $clean      = array();
    foreach ($dirty as $p => $data) {
        $data   = ereg_replace("[\'\")(;|`,<>]", "", $data);
        $data   = mysql_real_escape_string(trim($data));
        $data   = stripslashes($data);
        $clean[$p] = $data;
    }
    return $clean;
}

0
投票

使用mysql_real_escape_string意味着在使用该函数之前需要连接MySQL,这不是很方便。我曾经在这种情况下使用过解决方法:

function real_escape_string($aQuery) {
    if (!is_string($aQuery)) {
        return FALSE;
    } else {
        return strtr($aQuery, array( "\x00" => '\x00', "\n" => '\n', "\r" => '\r', '\\' => '\\\\', "'" => "\'", '"' => '\"', "\x1a" => '\x1a' ));
    }
}

但毫无疑问,最好是使用 PDO 准备好的语句而不是 mysql。你会喜欢它的。

© www.soinside.com 2019 - 2024. All rights reserved.