preg_replace& mysql_real_escape_string问题清理SQL

时间:2011-08-23 08:08:50

标签: php mysql preg-replace mysql-real-escape-string

查看以下方法。如果在文本框中输入的值为\ mysql_real_escape_string将返回duble反斜杠,但preg_replace将返回只有一个反斜杠的SQL。我对正则表达不太好,所以请帮忙。

$sql = "INSERT INTO tbl SET val='?'";
$params = array('someval');

public function execute($sql, array $params){
    $keys = array();

    foreach ($params as $key => $value) {
        $keys[] = '/[?]/';
        if (get_magic_quotes_gpc()) {
            $value = stripslashes($value);
        }
        $paramsEscaped[$key] = mysql_real_escape_string(trim($value));
    }

    $sql = preg_replace($keys, $paramsEscaped, $sql, 1, $count);
    return $this->query($sql);

}

2 个答案:

答案 0 :(得分:1)

最好使用预备语句。查看更多信息http://www.php.net/manual/en/pdo.prepared-statements.php

答案 1 :(得分:1)

对我来说,基本上看起来你正在重新发明轮子,你的概念有一些严重的缺陷:

  • 假设可以启用get_magic_quotes_gpc。此功能已损坏。你不应该对它进行编码。而是让您的应用程序要求关闭它。
  • mysql_real_escape_string需要数据库链接标识符才能正常工作。你没有提供任何。这是一个严重的问题,你应该改变你的观念。
  • 您实际上并未使用预准备语句,但您模仿了这些语法的语法。这是愚弄其他开发人员,他们可能认为使用代码是安全的,而不是。这是非常沮丧的。

但是,让我们这样做,但只是不要使用preg_replace来完成这项工作。这是出于各种原因,但尤其是,?的第一种模式导致用第一个参数替换所有内容。处理错误情况(例如太少或太多的参数/占位符)是不灵活的。另外想象一下,你插入的字符串也包含一个?字符。它会破坏它。相反,需要跳过已处理的部分以及替换部分(Demo of such)。

为此你需要经历,把它拆开并处理它:

public function execute($sql, array $params)
{
    $params = array_map(array($this, 'filter_value'), $params);

    $sql = $this->expand_placeholders($sql, $params);

    return $this->query($sql);
}

public function filter_value($value)
{
    if (get_magic_quotes_gpc())
    {
       $value = stripslashes($value);
    }
    $value = trim($value);
    $value = mysql_real_escape_string($value);
    return $value;
}

public function expand_placeholders($sql, array $params)
{
    $sql = (string) $sql;
    $params = array_values($params);
    $offset = 0;
    foreach($params as $param)
    {
        $place = strpos($sql, '?', $offset);
        if ($place === false)
        {
            throw new InvalidArgumentException('Parameter / Placeholder count mismatch. Not enough placeholders for all parameters.');
        }
        $sql = substr_replace($sql, $param, $place, 1);
        $offset = $place + strlen($param);
    }
    $place = strpos($sql, '?', $offset);
    if ($place === false)
    {
        throw new InvalidArgumentException('Parameter / Placeholder count mismatch. Too many placeholders.');
    }
    return $sql;
}

现有预备陈述的好处是,它们确实有效。你应该考虑使用它们。对于这样的游戏很不错,但是你最终需要处理更多的情况,并且重新使用由数千名其他用户测试的现有组件要容易得多。