codeigniter 3.1.13 不支持全局输出过滤机制,因其 output 类无后处理回调、set_output() 为覆盖式写入、无响应中间件环节;可行方案是封装基类控制器统一 render 并递归 xss_clean(需排除 ajax/json),或在视图中按需使用 html_escape()。

CodeIgniter 3.1.13 不提供开箱即用的「全局输出内容过滤规则」机制——它没有类似 $this->output->set_output_callback() 这样的钩子,也不支持在配置文件中统一注册 HTML/JS/XSS 清洗逻辑。所有输出过滤必须由开发者在控制器或视图层显式控制。
为什么不能直接配全局输出过滤
CI 3.x 的 Output 类设计上不预留输出内容的后处理回调;$this->output->set_output() 是覆盖式写入,不是管道式过滤;框架生命周期中也没有类似 Laravel 的 response 中间件环节。强行在 core/Output.php 里硬改会破坏升级兼容性,且无法区分 JSON、HTML、AJAX 等不同响应类型。
实际可行的替代方案:在控制器中统一 wrap 输出
最稳定的做法是封装一个基类控制器,在其 render() 或自定义方法中对最终数据做统一过滤,再交给 $this->load->view()。例如:
class MY_Controller extends CI_Controller
{
protected function render($view, $data = [])
{
// 对所有字符串型值做 xss_clean(仅限 HTML 响应)
if ($this->input->is_ajax_request() === FALSE) {
$data = $this->clean_recursive($data);
}
$this->load->view($view, $data);
}
protected function clean_recursive($value)
{
if (is_string($value)) {
return $this->security->xss_clean($value);
} elseif (is_array($value)) {
return array_map([$this, 'clean_recursive'], $value);
}
return $value;
}
}
- 所有业务控制器继承
MY_Controller,调用$this->render('home', $data)替代原生$this->load->view() - 避免对 JSON 响应误过滤:用
$this->input->is_ajax_request()或检查Content-Type头判断上下文 - 注意
$this->security->xss_clean()会修改 HTML 结构(如移除<script></script>、转义属性),不适合已信任的富文本字段
视图层手动加 html_escape() 是更安全的选择
比起在控制器层“一刀切”过滤,CI 官方推荐在视图中按需使用 html_escape()(CI 3.1.11+ 内置)或 htmlspecialchars(),尤其适用于动态变量输出:
<?php echo html_escape($user_name); ?><?php echo html_escape($post['content']); ?>
-
html_escape()是轻量级包装,只做htmlspecialchars($str, ENT_QUOTES, 'UTF-8'),不触发正则清洗,性能好、行为可预测 - 对富文本字段(如编辑器内容)不应使用,应单独存为
content_raw字段,并在视图中直接echo $post['content_raw'] - 模板中漏掉
html_escape()是 XSS 主要来源,建议团队代码审查时重点盯echo $开头的行
真正容易被忽略的是:JSON 接口响应如果也走同一套控制器基类过滤逻辑,xss_clean() 可能会把合法的 JSON 字符串(如含 的错误消息)误杀成空字符串——务必按响应类型分流处理,不要贪图“全局”二字。











