【问题标题】:CodeIgniter: SQL Audit of all $this->db->query() method calls?CodeIgniter:所有 $this->db->query() 方法调用的 SQL 审计?
【发布时间】:2011-12-15 04:36:27
【问题描述】:

我正在使用 CodeIgniter 2+ 并希望审核所有 $this->db->query($sql); 调用。

我们所有的数据库调用都是通过 query() 方法;没有活动记录使用。我需要记录 $sql 查询并将它们输入到自定义表中以进行审计记录。有没有人知道扩展核心系统数据库库以审计查询的方法?

看起来这应该很容易,但我似乎找不到简单的解决方案。 CI 论坛有几个关于旧版本的失败帖子。

【问题讨论】:

  • 如果可以访问服务器,可以尝试使用MySQL内置的query logging
  • 火箭,好主意。但是,我们将来可能会切换到 MS SQL 或 Oracle。我正在寻找基于 PHP 的解决方案。

标签: php mysql codeigniter audit


【解决方案1】:

这取决于您要如何审核它们。如果您正在寻找每页的基础,那么启用分析器就可以了。这显示了在该页面加载时运行的所有查询以及执行它们所花费的时间。请参阅分析器上的以下链接。

http://codeigniter.com/user_guide/general/profiling.html

如果您希望在所有查询发生时记录它们,然后稍后再读取日志文件,则必须扩展数据库类。如果是这种情况,请发表评论,我会进一步更新/扩展我的答案。

扩展覆盖query()

在 /application/core/ 中扩展 MY_Loader.php 并插入此函数

function database($params = '', $return = FALSE, $active_record = NULL)
    {
        // Grab the super object
        $CI =& get_instance();

        // Do we even need to load the database class?
        if (class_exists('CI_DB') AND $return == FALSE AND $active_record == NULL AND isset($CI->db) AND is_object($CI->db)) {
            return FALSE;
        }

        require_once(BASEPATH.'database/DB'.EXT);

        // Load the DB class
        $db =& DB($params, $active_record);

        $my_driver = config_item('subclass_prefix').'DB_'.$db->dbdriver.'_driver';
        $my_driver_file = APPPATH.'core/'.$my_driver.EXT;

        if (file_exists($my_driver_file)) {
            require_once($my_driver_file);
            $db = new $my_driver(get_object_vars($db));
        }

        if ($return === TRUE) {
            return $db;
        }

        // Initialize the db variable.  Needed to prevent
        // reference errors with some configurations
        $CI->db = '';
        $CI->db = $db;
    }

然后创建/application/core/MY_DB_mysql_driver.php

然后在里面你可以覆盖query()

function query($sql, $binds = FALSE, $return_object = TRUE) {
    // Do your stuff
    return parent::query( $sql, $binds, $return_object );
}

显然将文件名中的 mysql 替换为您正在使用/尝试扩展的任何数据库驱动程序。

这也适用于 Active Record,因为所有 get() 方法都会从驱动程序调用 query() 来运行它们的查询。

【讨论】:

  • 我还没有使用 Profiling 库。我需要在查询发生时(而不是最后)审核(记录)查询,并将每个查询保存为数据库表中的条目。我不确定 Profiler 能否帮助我解决这个问题。
  • 更新了我的答案,解释了如何在不触及核心的情况下覆盖数据库驱动程序类。
  • 谢谢 Ben,这可能是最好的方法。感谢所有对此问题发表评论的人。非常感谢,像往常一样。
  • 没问题 - 如果你让它为未来的读者使用它,请告诉我们。祝你好运:)
【解决方案2】:

如果你只是想直接这样做......

查询函数在 system/database/DB_driver.php 第 250 行(左右取决于您的版本)。

大约在第 289 行有一条评论说“运行查询”。

此时以任何你喜欢的方式输出$sql

【讨论】:

  • +1 - 覆盖核心不是一个好主意,但由于您无法扩展 db 类,这可能是无需重写已有代码的最佳解决方案。
  • 在我看来,codeigniter 很好但不是很好。没有理由不按照你的意愿修改它的代码。也就是说,另一种方法是使用所有其他人扩展的自定义模型类。它们都调用了调用$this->db->query() 的父方法。完成后,您可以致电$this->db->last_query() 并记录它。或者您可以使用 SQL 层日志查询。
  • 定制模型可能是要走的路。如有必要,我什至可以在实际运行之前记录查询。所有模型都需要使用的 database_model.php。
  • 如果没有人使用 db 方法来帮助构建查询,您只能在运行查询之前记录查询。如果您要创建自定义模型,您可以通过将MY_Model.php 放入application/core/ 轻松完成
【解决方案3】:

貌似可以扩展数据库类,覆盖query方法,但是according to Phil,不行。

一种解决方案是创建一个辅助方法,您可以将所有$this->db->query 调用替换为将记录您的查询,然后调用query 方法。

更新

您可以创建一个复制 Profiler 库的 _compile_queries 方法的库(https://github.com/EllisLab/CodeIgniter/blob/develop/system/libraries/Profiler.php 的第 168 行)。通常,此方法将所有查询输出到浏览器,但您可以以记录所有查询的方式实现它。那么,您不仅会得到使用$this->db->query 生成的查询,而且所有查询都会运行。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-29
    • 2023-03-27
    • 2017-04-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多