3

我有一个包含大量 PHP 文件(真的很多......)的网站,这些文件使用pg_querypg_exec函数不会在 Postgre SQL 查询中转义撇号。

但是,出于安全原因以及在我的数据库中存储带有撇号的名称的能力,我想为我的数据库输入添加一个转义机制。一种可能的解决方案是检查每个 PHP 文件并更改pg_querypg_exec使用pg_query_params,但这既费时又容易出错。一个好主意是以某种方式覆盖pg_queryandpg_exec来包装函数,这些函数可以在不必更改任何 PHP 文件的情况下进行转义,但在这种情况下,我想我将不得不更改 PHP 函数定义并重新编译它,这不是很理想。

所以,这个问题是开放的,任何可以用最少的时间做我想做的事情的想法都是非常受欢迎的。

4

2 回答 2

3

你没有发布代码,但我猜你有这个:

$name = "O'Brian";
$result = pg_query($conn, "SELECT id FROM customer WHERE name='{$name}'");

...你需要有这个:

$name = "O'Brian";
$result = pg_query_params($conn, 'SELECT id FROM customer WHERE name=$1', array($name));

...但您认为该任务将消耗不合理的时间。

虽然它肯定很复杂,但您有什么选择?您不能覆盖pg_query(),但搜索和替换它会非常简单my_pg_query()。现在呢?您的自定义函数只会看到字符串:

SELECT id FROM customer WHERE name='O'Brian'
SELECT id FROM customer WHERE name='foo' OR '1'='1'

即使您设法实现了一个无错误的 SQL 解析器:

  1. 它不能可靠地处理无效的 SQL。
  2. 它将无法确定查询是否是故意 SQL 注入的产物。

放轻松,一一修复查询。这需要时间,但可能没有你想象的那么多。随着您的进步,您的应用程序会越来越好。

于 2012-12-20T10:45:55.463 回答
2

这是数据库层和相关 API 何时可以为您节省大量时间的完美示例。一个好的解决方案是将 DB 类作为单例,您可以从应用程序的任何位置对其进行实例化。一组简单的包装函数将允许您对数据库的所有查询都通过一个点,因此您可以非常轻松地更改它们的工作方式。您还可以从一个数据库更改为另一个数据库,或从一个数据库供应商更改为另一个数据库供应商,而无需触及应用程序的其余部分。

通过使用PDO接口而不是像 pg_query() 这样的函数,可以很好地解决转义问题,这使得转义变得不必要。鉴于您必须在应用程序中使用 DB 的任何地方进行更改,您不妨重构以同时使用此模式,因为它的工作量相同。

class db_wrapper {

    // Singleton stuff
    private $instance;

    private function __construct() {
        // Connect to DB and store connection somewhere
    }

    public static function get_db() {
        if (isset($instance)) {
            return $instance;
        }
        return $instance = new db_wrapper();
    }

    // Public API

    public function query($sql, array $vars) {
        // Use PDO to connect to database and execute query
    }

}

// Other parts of your app look like this:

function do_something() {
    $db = db_wrapper::get_db();
    $sql = "SELECT * FROM table1 WHERE column = :name";
    $params = array('name' => 'valuename');
    $result = $db->query($sql, $params);

    // Use $result for something. 
}
于 2012-12-20T10:39:45.823 回答