通过GET,POST和COOKIE循环消毒?

时间:2009-07-27 15:06:47

标签: php mysql validation sanitization

考虑到每个人总是担心用户数据(并且正确),只要在获得它时简单地遍历每个外部数组就足够了,并应用mysql_real_escape_string()。

我很好奇这是不是一个坏主意。

类似的东西:

function getExternalData($type='GET')
{
    $type = strtoupper($type);
    $data = $_$type;
    foreach($data as $key => $value)
    {
        $clean[$key] = mysql_real_escape_string($value);
    }
    return $clean;
}

这将使所有数据在数据库中安全使用。但是,这样做的缺点是什么?

6 个答案:

答案 0 :(得分:2)

在所有超全局变量上应用mysql_real_escape_string会让人觉得你要么在MySQL查询中专门使用它们,要么你不知道mysql_real_escape_string有什么好处。

答案 1 :(得分:2)

主要的想法是,如果你必须处理输入,例如为了解析标记,你必须取消输入,然后不要忘记重新转义它。而且,这是非常低效的。查询占位符是防止SQL注入的一种非常好的方法。

至于清理本身(不仅适用于SQL),您应该查看Filter extension,默认情况下在PHP 5.2中可用,在PECL中可用于5.1。

答案 2 :(得分:1)

缺点:

您可能会忘记其他类型的用户输入,因此,不要清理它们 而且,当然,多余的循环 并且,我认为数据库清理应该尽可能最新,就在您将数据输入DL中的数据库之前 用于演示的清洁数据应在呈现数据等之前完成。

那就是说,在你尝试这种方法之前,你永远不会知道,因为人们通常不同意他们不使用自己的方法(见上文:-))

答案 3 :(得分:1)

不要尝试清理数据。对占位符使用查询。见bobby-tables.com

答案 4 :(得分:1)

我认为概括验证和过滤逻辑是个坏主意。毕竟这是魔术引号背后的想法,现在普遍受到谴责。

除此之外,验证字段输入通常涉及大量特定垃圾。通用规则只是验证的一小部分,特别是随着应用程序的大小和复杂性的增加。

最好提出一个迷你框架,允许您在同一个地方处理通用和特定验证。像这样......

class BrokenRules extends Exception {
    protected $errors;
    function __construct($errors) {
        $this->errors = $errors;
    }
    function getErrors() {
        return $this->errors;
    }
}

class Foo {
    protected $db;
    function __construct(PDO $db) {
        $this->db = $db;
    }
    function loadNew() {
        return array('bar' => 'new foo', 'baz' => 5);
    }
    function loadById($id) {
        $stmt = $this->db->prepare('SELECT * FROM foo WHERE id = ?');
        $stmt->bindValue(1, $id, PDO::PARAM::INT);
        $stmt->execute();
        return $stmt->fetch();
    }
    function save($data) {
        return isset($data['id']) ? $this->update($data) : $this->insert($data);
    }
    protected function validateForInsert($data) {
        if ((int)$data['baz'] <= 3) $errors['baz'][] = 'Baz must be greater than 3';
        if (isset($errors)) throw new BrokenRules($errors);
    }
    protected function validateForUpdate($data) {
        // TODO: validateForUpdate
    }
    protected function insert($data) {
        $this->validateForInsert($data);
        $stmt = $this->db->prepare('INSERT INTO foo (x, y) VALUES (?, ?)');
        $stmt->bindValue(1, $data['bar'], PDO::PARAM_STR);
        $stmt->bindValue(2, $data['baz'], PDO::PARAM_INT);
        $stmt->execute();
        return $this->db->lastInsertId();
    }
    protected function update($data) {
        $this->validateForUpdate($data);
        $stmt = $this->db->prepare('UPDATE foo SET x = ?, y = ? WHERE id = ?');
        $stmt->bindValue(1, $data['bar'], PDO::PARAM_STR);
        $stmt->bindValue(2, $data['baz'], PDO::PARAM_INT);
        $stmt->bindValue(3, $data['id'], PDO::PARAM_INT);
        $stmt->execute();
        return $data['id'];
    }
}

try {
    $foo = new Foo($pdo);
    if ($_POST) {
        $id = $foo->save($_POST);
        redirect("edit_foo.php?id=$id");
    } else if (isset($_GET['id'])) {
        $data = $foo->loadById($_GET['id']);
    } else {
        $data = $foo->loadNew();
    }
} catch (BrokenRules $e) {
    $errors = $e->getErrors();
}

include 'templates/foo.php';

答案 5 :(得分:0)

我认为你实际上在寻找array_map()。这消除了对循环的需要。是的,这对于为数据库提供安全请求是可以接受的。

但有一点,你可能想在这里使用$_SERVER['REQUEST_METHOD']。 (除非你使用它作为参数传递给这个函数。)