0

考虑到每个人总是担心用户数据(并且正确地如此),当你得到它时简单地循环遍历每个外部数组并应用 mysql_real_escape_string() 就足够了。

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

就像是:

函数 getExternalData($type='GET')
{
    $type = strtoupper($type);
    $数据= $_$类型;
    foreach($data as $key => $value)
    {
        $clean[$key] = mysql_real_escape_string($value);
    }
    返回$清洁;
}

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

4

6 回答 6

2

应用于mysql_real_escape_string所有超全局变量会传达出一种印象,即您要么只想在 MySQL 查询中使用它们,要么不知道有什么mysql_real_escape_string好处。

于 2009-07-27T15:22:56.443 回答
2

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

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

于 2009-07-27T15:24:59.387 回答
1

缺点:

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

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

于 2009-07-27T15:11:44.063 回答
1

不要试图清理数据。使用带有占位符的查询。请参阅bobby-tables.com

于 2009-07-27T15:17:10.777 回答
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';
于 2009-07-27T18:24:52.677 回答
0

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

不过有一件事,您可能想在这里使用$_SERVER['REQUEST_METHOD']。(除非您使用它作为参数传递给此函数。)

于 2009-07-27T15:13:44.903 回答