
HTML Purifier 会自动转义特殊字符(如 & → &)并标准化 Unicode 实体(如 ø → ø),导致直接比对原始与净化后字符串无法准确识别“真实修改”。推荐使用内置的 Core.CollectErrors 功能捕获语义级变更,而非依赖字符串差异比对。
html purifier 会自动转义特殊字符(如 `& → &`)并标准化 unicode 实体(如 `ø → ø`),导致直接比对原始与净化后字符串无法准确识别“真实修改”。推荐使用内置的 `core.collecterrors` 功能捕获语义级变更,而非依赖字符串差异比对。
HTML Purifier 的设计目标是安全优先,而非输出保真。这意味着即使输入 HTML 本身是合法且无害的,Purifier 仍可能对其执行以下不可逆转换:
- 所有裸露的 HTML 特殊字符(&, )一律实体化(如 & → &);
- 非 ASCII Unicode 字符默认以 UTF-8 原生字节形式输出(如 ø),而非保留其命名实体(ø)或十进制实体(ø);
- 属性值引号标准化、空白折叠、标签闭合补全等结构优化。
这些行为虽不引入安全风险,但会使简单的字符串 diff(如 str_replace() 或 diff() 工具)产生大量“伪变更”,掩盖真正被移除/重写的危险内容(如 <script> 标签、onerror 事件、非法协议 javascript: 等)。</script>
✅ 正确做法:启用错误收集器(Error Collector)
HTML Purifier 提供了 Core.CollectErrors 配置项,专为审计目的设计。它在解析过程中记录所有语义级干预操作,包括:
- 被删除的标签/属性
- 被修改的属性值(如 href="javascript:..." → href="#")
- 被规范化的内容(如 → 保持不变,但 & → & 不计入——因属强制安全转义,非“修正”)
示例代码如下:
require_once 'htmlpurifier/library/HTMLPurifier.auto.php';
$config = HTMLPurifier_Config::createDefault();
$config->set('Core.CollectErrors', true); // 启用变更日志
$config->set('HTML.Allowed', 'p,b,i,a[href],ul,li'); // 示例白名单
$purifier = new HTMLPurifier($config);
$dirtyHtml = '<p>Hello & oslash; <script>alert(1)</script><a href="javascript:evil()">click</a></p>';
$cleanHtml = $purifier->purify($dirtyHtml);
// 获取变更详情
$errorCollector = $purifier->context->get('ErrorCollector');
if ($errorCollector) {
$rawErrors = $errorCollector->getRaw(); // 返回数组:[line, col, severity, message, context]
foreach ($rawErrors as $err) {
echo sprintf("[%s] %s\n", $err[2], $err[3]); // 如:[Warning] Removed script tag
}
}
⚠️ 注意事项:
- Core.CollectErrors 默认关闭,需显式启用;
- 它不记录 & → & 这类底层安全转义(这是预期行为,非“错误”),只报告策略驱动的主动干预;
- 若需强制统一实体输出(如兼容旧系统),可配合 Core.EscapeNonASCIICharacters = true,但会增加体积且无助于审计——仅作备选;
- 日志中的 line/col 基于原始 HTML(非净化后),便于精确定位源位置。
总结:放弃基于字符串 diff 的日志方案,转向 ErrorCollector 是唯一可靠、轻量且符合 Purifier 设计哲学的审计路径。它将你的日志从“字符级噪音”升级为“语义级决策日志”,真正聚焦于安全策略的实际影响。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











