esc()是CodeIgniter 4引入的视图转义函数,CI3中不存在,应使用html_escape()替代,且需先加载html辅助函数;富文本须用HTMLPurifier白名单过滤,不可依赖xss_clean()。

CodeIgniter 3 没有 esc() 函数
直接说结论:esc() 是 CodeIgniter 4 引入的视图专用输出转义函数,CI3 中根本不存在。如果你在 CI3 项目里写了 = esc($user_input) ?>,会触发 Fatal error: Call to undefined function esc()。
CI3 的等效函数是 html_escape()(全局辅助函数),它默认做 HTML 上下文转义,行为接近 esc($str, 'html')。
常见错误现象:复制 CI4 教程代码到 CI3 项目,页面白屏或报错;用 htmlspecialchars() 手动包裹但漏掉编码参数,导致中文乱码或单引号未转义。
- 必须先加载
url或html辅助函数(任一即可),html_escape()才可用:$this->load->helper('html'); -
html_escape()不支持上下文参数(如'js'或'url'),只做基础 HTML 实体转义 - 若需 JS 字符串输出,得手动用
addslashes()+ 单引号包裹,或改用json_encode($str, JSON_HEX_TAG | JSON_HEX_AMP)
在 CI3 视图中安全输出用户数据的正确写法
所有来自数据库、表单提交、URL 参数、Cookie 等不可信来源的数据,在视图中输出前都必须经过转义 —— 不能依赖输入时的 xss_clean(),那是另一层且已过时的防护。
示例场景:显示用户昵称、评论内容、搜索关键词高亮片段。
- HTML 内容(段落、标题):
<p><?php echo html_escape($comment); ?></p> - HTML 属性值(
title、alt):<img src="avatar.jpg" alt="<?php echo html_escape($user_name); ?>"> - JavaScript 字符串(慎用!优先用 data-* 属性传值):
<script>var name = <?php echo json_encode($user_name, JSON_HEX_TAG | JSON_HEX_AMP); ?>;</script> - URL 参数拼接(如跳转链接):
<a href="profile.php?id=<?php echo rawurlencode($id); ?>">查看</a>(注意:这里用rawurlencode(),不是html_escape())
为什么不能只靠 $this->security->xss_clean() 输入过滤
xss_clean() 在 CI3 中是输入阶段的启发式清洗,它不解析 HTML、易被大小写/空格/注释绕过,且对 SVG、CSS expression、data: URL 等现代 XSS 变体基本无效。2026 年的攻击手法早已绕过它。
更关键的是:它只应在「输入即存储、且后续纯文本展示」的极低风险场景下作为辅助手段,比如后台系统通知标题字段。一旦数据要渲染进 HTML、JS 或 CSS 上下文,xss_clean() 就完全失能。
- 常见错误:在控制器里调用
$this->security->xss_clean($input)后,视图中直接= $cleaned_input ?>—— 这等于把转义责任推给输入层,违反“输出时按上下文转义”原则 - 性能影响:每次调用
xss_clean()都触发正则扫描,对长文本开销明显,尤其在循环中使用 - 兼容性陷阱:CI4 已彻底移除该函数,升级时若大量依赖它,重构成本极高
富文本内容怎么处理才不算裸奔
如果业务真需要保留部分 HTML(如用户发帖带加粗、列表),html_escape() 会把所有标签变成纯文本,显然不行。这时必须引入白名单过滤,而非清洗或简单转义。
推荐组合:HTMLPurifier(稳定、标准、可配) + 输出前调用 + 严格限制标签与属性。
- 不要用 CI3 自带的
strip_tags()白名单模拟,它不解析 DOM,无法防御<div onclick="alert(1)">类攻击 - 避免在视图中动态初始化
HTMLPurifier实例,应提前在控制器或模型中净化并缓存结果 - 配置示例关键项:
$config->set('HTML.Allowed', 'p,b,i,br,ul,ol,li,a[href|title]');—— 明确放行哪些标签及允许的属性 - 净化后仍需用
html_escape()包裹?不需要。HTMLPurifier 输出已是安全 HTML,直接= $sanitized_html ?>即可
真正容易被忽略的点:富文本字段的数据库存储长度是否足够?TEXT 类型可能不够,而 MEDIUMTEXT 又可能被滥用为存储恶意 payload 容器 —— 净化必须在入库前完成,不能只做输出时兜底。


















