
HTML Purifier 默认会对特殊字符(如 &)进行安全转义,并将 Unicode 字符(如 ø)以 UTF-8 原生形式输出,导致原始与净化后字符串的字面差异无法准确反映「实际过滤行为」;推荐启用 Core.CollectErrors 获取精准的结构化变更记录,而非依赖字符串比对。
html purifier 默认会对特殊字符(如 `&`)进行安全转义,并将 unicode 字符(如 `ø`)以 utf-8 原生形式输出,导致原始与净化后字符串的字面差异无法准确反映「实际过滤行为」;推荐启用 `core.collecterrors` 获取精准的结构化变更记录,而非依赖字符串比对。
HTML Purifier 的核心设计目标是安全优先,而非语义或格式保真。这意味着即使输入 HTML 本身是合法且无害的,Purifier 仍可能对其进行如下不可见但语义等价的转换:
- & → &(所有未被实体化的 HTML 特殊字符均强制转义,无论上下文是否安全)
- ø → ø(内部统一使用 UTF-8 编码表示 Unicode 字符,而非保留命名实体)
这类转换并非“错误”,而是 Purifier 深度解析、规范化 DOM 树后的自然结果。因此,直接对原始字符串与净化后字符串做 === 或 diff 比较,会混入大量非安全相关的“伪变更”,干扰你对真实过滤行为(如标签删除、属性剥离、危险脚本移除)的判断。
✅ 正确方案:使用 Core.CollectErrors
HTML Purifier 提供了专为审计与调试设计的 Core.CollectErrors 配置项,它会在净化过程中主动收集所有结构性修改事件(如元素被移除、属性被清理、危险内容被替换),并以结构化数组形式返回,完全规避字符编码层面的干扰。
启用方式如下:
require_once '/path/to/HTMLPurifier.auto.php';
$config = HTMLPurifier_Config::createDefault();
$config->set('Core.CollectErrors', true); // 启用错误/变更收集
$config->set('HTML.Allowed', 'p,b,i,a[href]'); // 示例白名单
$purifier = new HTMLPurifier($config);
$dirtyHtml = '<p>Hello & <a href="javascript:alert(1)">click</a> ø</p>';
$cleanHtml = $purifier->purify($dirtyHtml);
// 获取变更日志
$errorCollector = $purifier->context->get('ErrorCollector');
$changes = $errorCollector->getRaw(); // 返回包含 type、line、col、message 的数组
print_r($changes);
// 输出示例:
// Array(
// [0] => Array(
// [type] => RemovedAttribute
// [line] => 1
// [col] => 32
// [message] => Attribute 'href' on element 'a' not supported
// )
// [1] => Array(
// [type] => AutoParagraph
// [line] => 1
// [col] => 0
// [message] => Auto-p was added to paragraph
// )
// )
⚠️ 注意事项:
- Core.CollectErrors 不捕获纯编码转换(如 & → &),只记录安全策略驱动的显式操作,这正是你日志需求的本质;
- 该功能稳定可用,文档中“experimental”提示已过时,生产环境可放心启用;
- 若需进一步区分“警告”与“错误”,可通过 $errorCollector->getMessages() 获取用户友好文本,或遍历 $errorCollector->getRaw() 中的 type 字段(如 RemovedElement, AttrRemoved, BadChild 等)做分类统计。
❌ 不推荐的替代方案
- 强制启用 Core.EscapeNonASCIICharacters:虽能将所有非 ASCII 字符转为实体(如 ø → ø),但会破坏 UTF-8 原生输出优势,增加体积,且仍无法解决 & → & 类转义问题;
- 预解码 + 后编码再比对:手动 html_entity_decode() 原始内容再与净化结果比较,极易因编码不一致(如 mb_internal_encoding 设置)引发乱码或误判,违背 Purifier 的设计契约。
总结
要构建可靠的内容净化审计日志,请始终信任 Purifier 内置的 Core.CollectErrors 机制——它提供的是意图明确、语义清晰、与安全策略强绑定的变更事实,而非易受编码表征干扰的字面差异。将日志逻辑从「字符串 diff」升级为「事件流消费」,是实现可维护、可验证、可追溯的 HTML 净化流程的关键一步。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











