codeigniter 审计日志需手动实现:启用钩子(post_controller)、结合 session/input 获取用户/ip上下文、用log_message记录结构化信息,避免原生$_session/$_server,确保事务提交后再捕获sql。

CodeIgniter 默认不记录用户活动,必须手动介入请求生命周期——靠钩子、log_message() 或 Session/Input 组合才能拿到“谁在什么时间做了什么”。
用 post_controller 钩子捕获数据库变更最省事
这是全局审计的起点,不用改每个控制器,但前提是已开启钩子且确保事务已提交。
-
$config['enable_hooks'] = TRUE必须写在application/config/config.php里,否则钩子完全不生效 - 钩子点选
post_controller而非post_system:前者能访问$this->db->queries,后者已释放 DB 实例 - 事务未提交时
$this->db->queries为空,所以别在事务中间触发日志;建议只记录明确的INSERT/UPDATE/DELETE,用正则加\b边界符防误匹配(如INSERTED) - 用户身份得从 Session 拿:
$this->CI->session->userdata('user_id'),不能依赖$_SESSION原生数组,CI 的 session 可能加密或存数据库
log_message() 记关键业务动作更可控
登录、下单、删除资源这类有明确语义的操作,硬编码日志比钩子更可靠,也更容易加结构化字段。
- 别直接拼接用户输入:
log_message('info', 'user_login|id:'.$_POST['id'])是危险写法,应先过html_escape()或strip_tags() - 推荐用竖线分隔的伪结构:
log_message('info', 'user_login|id:'.$user_id.'|ip:'.$this->input->ip_address()),方便后续 grep 或日志系统解析 - 日志级别选
info或debug,但生产环境若设$config['log_threshold'] = 1,info级别会被忽略——得调成 2 或以上 - 避免在循环里高频调用
log_message(),文件 I/O 会拖慢响应;高频操作(如点击流)建议先缓存再批量写
Session + Input 类是还原用户上下文的唯一靠谱组合
单记“执行了 UPDATE users SET status=1”没意义,必须绑定身份、IP、来源页这些上下文,否则日志等于废纸。
-
$this->session->userdata('user_id')是最可信的身份标识,但前提是登录逻辑确实调用了$this->session->set_userdata() -
$this->input->ip_address()比$_SERVER['REMOTE_ADDR']强,能穿透常见代理;但遇到多层 CDN 仍可能不准,别用它做权限判断 -
$this->input->server('HTTP_REFERER')可读但不可信,字段可能为空、被篡改或截断,仅适合辅助分析跳转路径 - 别用
$this->input->user_agent()做安全校验——它完全由客户端发送,伪造成本为零
真正难的不是写几行日志,而是让每条记录都带可追溯的上下文;漏掉 IP 或 user_id,审计时就只剩一堆无法归属的 SQL 语句。











