HTML 实体编码的工作原理
HTML 实体是一种字符引用,浏览器在解析时会将其还原为单个字符。五个 HTML 保留字符(<、>、&、"、')在文本渲染为 HTML 时必须编码;其他字符是否编码取决于文档编码。
- 选择模式和范围. 编码模式逐字符处理输入;解码模式则扫描实体模式。范围开关决定仅对五个 HTML 安全字符编码,还是同时对所有非 ASCII 码点进行转义。
- 选择实体样式. 命名实体(
©)在源码中易于阅读。十进制引用(©)和十六进制引用(©)可表示任意 Unicode 码点,无需名称。旧版邮件客户端和 XML 解析器更倾向于使用数字形式。 - 逐字符遍历输入. 编码时,工具逐码点读取并在约 200 个常用命名实体表中查找。未命中则回退为数字形式。解码时,单个正则表达式在一次遍历中匹配
&name;、&#NNN;和&#xHH;三种形式。 - 映射到字符. 命名匹配通过反向表解析。数字匹配通过
String.fromCodePoint以十进制或十六进制处理。未知命名实体保持原样,确保不完整输入在往返转换中不丢失。 - 实时模式. 开启实时模式后,每次按键均会以 150 毫秒防抖重新执行转换。在微调代码片段并希望在粘贴到模板前立即看到结果时非常实用。
为什么要对 HTML 实体进行编码
- 防止用户输入破坏页面布局. 当用户在评论框中输入
<时,若将文本直接插入 HTML,会导致后续页面内容被重写。对保留字符进行编码后,浏览器将其渲染为字符而非标签的开头。 - 保持属性值的有效性. 在 HTML 属性中嵌入带引号的字符串,需将内嵌引号替换为
"(双引号属性)或'(单引号属性),否则解析器会提前关闭属性,导致后续内容变为无效标记。 - 消除存储数据中的意外 HTML. 日志、错误报告和聊天导出中常含有真实的尖括号与 & 符号。在粘贴到文档页面前对这些内容进行实体编码,可确保其作为文本显示,而非触发渲染器或链接自动检测。
- 安全分享代码片段. 在博客文章、电子邮件或即时消息中发布示例标签(如
<script>alert(1)</script>)时,需对尖括号编码以确保代码只被显示而非执行。同样的技术适用于 RSS feed 正文和 JSON-LD 的 `description` 字段。
常见应用场景
实体编码出现在任何将原始文本动态组合进 HTML 的场景中 — 即使框架通常会自动处理,在特殊情况下手动工具仍然不可或缺。
- 服务端渲染模板:Jinja2、ERB、Twig 和 Handlebars 默认自动转义,但 raw 块和 `safe` 标记会关闭该功能 — 本工具可帮助确认转义结果是否符合预期。
- 电子邮件与通讯:许多 ESP 模板引擎不会对合并字段自动转义,用户姓名中的引号和版权符号需要预先编码。
- 文档与代码示例:将 HTML 标签粘贴到 Markdown 博客或静态站点片段时,需对尖括号编码以确保渲染器将其视为可见文本。
示例演示
将 <script>alert('hi')</script> 粘贴到输入框,模式设为「编码」,样式选「命名」,范围选「最小化」。输出为 <script>alert('hi')</script>。将样式切换为「数字十六进制」,相同输入则输出 <script>alert('hi')</script>。将模式切换为「解码」并粘贴已编码字符串,即可还原原始标签。
FAQ
什么是 HTML 实体?
HTML 实体是字符引用,浏览器解析页面时会将其还原为单个字符。共有三种形式:命名形式(如 & 代表 &)、十进制数字形式(&)和十六进制数字形式(&)。五个 HTML 保留字符(<、>、&、"、')在文本插入 HTML 时必须编码。其余约 2,225 个命名实体涵盖符号、重音字符和希腊字母,在文档编码为 UTF-8 时均为可选。
何时应使用命名实体,何时使用数字实体?
当希望源码易于阅读时使用命名实体(审查模板时看到 © 一目了然)。当消费方较旧或要求更严格时使用数字形式 — XML 解析器、旧版邮件客户端和部分 Feed 阅读器仅识别少量 HTML5 命名实体,但全部支持数字形式。在安全相关场景中,十六进制形式更受青睐,因为它与规范文档中使用的 Unicode 码点记法一一对应。
解码器能处理十六进制实体(如 &)吗?
可以。解码器使用单个正则表达式在一次遍历中匹配三种实体形式:&name;、&#NNN; 和 &#xHH;。数字匹配通过 String.fromCodePoint 以十进制或十六进制处理。混合输入(命名实体和数字实体并存)可正确解码;未知名称以字面文本保留,确保不完整输入往返转换不丢失。
处理不可信输入时是否安全?
本编解码器完全在浏览器端运行,不会将输入发送至任何地方。输出是否可安全嵌入取决于上下文。实体编码适用于 HTML 正文和属性值上下文,覆盖了 OWASP 规则 #1 的场景。JavaScript 上下文(内联事件处理程序、`<script>` 块)、CSS 上下文和 URL 上下文各有其编码规则 — 仅凭实体编码不足以应对这些场景。在服务端纵深防御中,建议配合 DOMPurify 等上下文感知模板引擎或框架内置的自动转义机制一同使用。
在浏览器端进行实体编码,位于用户输入与 HTML 渲染的交界处。本地转换意味着您可以验证框架所生成的输出,而无需将原始文本发送至任何第三方工具。