§

输入

模式
实体样式
编码范围
§

输出

在国内 Web 安全合规实践中,HTML 实体编码是防范跨站脚本攻击的核心手段。国家标准 GB/T 32907-2016 虽直接规范 SM4 分组密码,但其配套的 Web 安全实施指南将输出编码列为 XSS 防御基线;阿里云 JFinal 开发框架官方文档明确要求在渲染用户输入时调用 `HtmlUtil.escape` 完成 HTML 实体转义;腾讯云 Web 应用防火墙的 XSS 检测规则也将未转义的尖括号与 `&` 符号视为高危信号。此在浏览器端运行的编解码工具无需联网,可供安全评审或代码审计时快速核验输出是否符合上述规范。

HTML 实体编码的工作原理

HTML 实体是一种字符引用,浏览器在解析时会将其还原为单个字符。五个 HTML 保留字符(<、>、&、"、')在文本渲染为 HTML 时必须编码;其他字符是否编码取决于文档编码。

  1. 选择模式和范围. 编码模式逐字符处理输入;解码模式则扫描实体模式。范围开关决定仅对五个 HTML 安全字符编码,还是同时对所有非 ASCII 码点进行转义。
  2. 选择实体样式. 命名实体(&copy;)在源码中易于阅读。十进制引用(&#169;)和十六进制引用(&#xA9;)可表示任意 Unicode 码点,无需名称。旧版邮件客户端和 XML 解析器更倾向于使用数字形式。
  3. 逐字符遍历输入. 编码时,工具逐码点读取并在约 200 个常用命名实体表中查找。未命中则回退为数字形式。解码时,单个正则表达式在一次遍历中匹配 &name;&#NNN;&#xHH; 三种形式。
  4. 映射到字符. 命名匹配通过反向表解析。数字匹配通过 String.fromCodePoint 以十进制或十六进制处理。未知命名实体保持原样,确保不完整输入在往返转换中不丢失。
  5. 实时模式. 开启实时模式后,每次按键均会以 150 毫秒防抖重新执行转换。在微调代码片段并希望在粘贴到模板前立即看到结果时非常实用。

为什么要对 HTML 实体进行编码

  • 防止用户输入破坏页面布局. 当用户在评论框中输入 < 时,若将文本直接插入 HTML,会导致后续页面内容被重写。对保留字符进行编码后,浏览器将其渲染为字符而非标签的开头。
  • 保持属性值的有效性. 在 HTML 属性中嵌入带引号的字符串,需将内嵌引号替换为 &quot;(双引号属性)或 &#39;(单引号属性),否则解析器会提前关闭属性,导致后续内容变为无效标记。
  • 消除存储数据中的意外 HTML. 日志、错误报告和聊天导出中常含有真实的尖括号与 & 符号。在粘贴到文档页面前对这些内容进行实体编码,可确保其作为文本显示,而非触发渲染器或链接自动检测。
  • 安全分享代码片段. 在博客文章、电子邮件或即时消息中发布示例标签(如 <script>alert(1)</script>)时,需对尖括号编码以确保代码只被显示而非执行。同样的技术适用于 RSS feed 正文和 JSON-LD 的 `description` 字段。

常见应用场景

实体编码出现在任何将原始文本动态组合进 HTML 的场景中 — 即使框架通常会自动处理,在特殊情况下手动工具仍然不可或缺。

  • 服务端渲染模板:Jinja2、ERB、Twig 和 Handlebars 默认自动转义,但 raw 块和 `safe` 标记会关闭该功能 — 本工具可帮助确认转义结果是否符合预期。
  • 电子邮件与通讯:许多 ESP 模板引擎不会对合并字段自动转义,用户姓名中的引号和版权符号需要预先编码。
  • 文档与代码示例:将 HTML 标签粘贴到 Markdown 博客或静态站点片段时,需对尖括号编码以确保渲染器将其视为可见文本。

示例演示

<script>alert('hi')</script> 粘贴到输入框,模式设为「编码」,样式选「命名」,范围选「最小化」。输出为 &lt;script&gt;alert(&#39;hi&#39;)&lt;/script&gt;。将样式切换为「数字十六进制」,相同输入则输出 &#x3C;script&#x3E;alert(&#x27;hi&#x27;)&#x3C;/script&#x3E;。将模式切换为「解码」并粘贴已编码字符串,即可还原原始标签。

FAQ

什么是 HTML 实体?

HTML 实体是字符引用,浏览器解析页面时会将其还原为单个字符。共有三种形式:命名形式(如 &amp; 代表 &)、十进制数字形式(&#38;)和十六进制数字形式(&#x26;)。五个 HTML 保留字符(<>&"')在文本插入 HTML 时必须编码。其余约 2,225 个命名实体涵盖符号、重音字符和希腊字母,在文档编码为 UTF-8 时均为可选。

何时应使用命名实体,何时使用数字实体?

当希望源码易于阅读时使用命名实体(审查模板时看到 &copy; 一目了然)。当消费方较旧或要求更严格时使用数字形式 — XML 解析器、旧版邮件客户端和部分 Feed 阅读器仅识别少量 HTML5 命名实体,但全部支持数字形式。在安全相关场景中,十六进制形式更受青睐,因为它与规范文档中使用的 Unicode 码点记法一一对应。

解码器能处理十六进制实体(如 &)吗?

可以。解码器使用单个正则表达式在一次遍历中匹配三种实体形式:&name;&#NNN;&#xHH;。数字匹配通过 String.fromCodePoint 以十进制或十六进制处理。混合输入(命名实体和数字实体并存)可正确解码;未知名称以字面文本保留,确保不完整输入往返转换不丢失。

处理不可信输入时是否安全?

本编解码器完全在浏览器端运行,不会将输入发送至任何地方。输出是否可安全嵌入取决于上下文。实体编码适用于 HTML 正文和属性值上下文,覆盖了 OWASP 规则 #1 的场景。JavaScript 上下文(内联事件处理程序、`<script>` 块)、CSS 上下文和 URL 上下文各有其编码规则 — 仅凭实体编码不足以应对这些场景。在服务端纵深防御中,建议配合 DOMPurify 等上下文感知模板引擎或框架内置的自动转义机制一同使用。

在浏览器端进行实体编码,位于用户输入与 HTML 渲染的交界处。本地转换意味着您可以验证框架所生成的输出,而无需将原始文本发送至任何第三方工具。