Element: setHTML() 方法

可用性有限

此特性不是基线特性,因为它在一些最广泛使用的浏览器中不起作用。

实验性: 这是一项实验性技术
在生产中使用此技术之前,请仔细检查浏览器兼容性表格

Element 接口的 setHTML() 方法提供了一种 XSS 安全的方法,用于解析和清理 HTML 字符串并将其转换为 DocumentFragment,然后作为元素子树插入到 DOM 中。

语法

js
setHTML(input)
setHTML(input, options)

参数

input

定义要清理并注入到元素中的 HTML 字符串。

options 可选

一个包含以下可选参数的 options 对象

sanitizer

一个 SanitizerSanitizerConfig 对象,用于定义输入中允许或删除的元素,或者字符串 "default" 表示默认配置。请注意,如果配置要重复使用,通常 SanitizerSanitizerConfig 更高效。如果未指定,则使用默认的 Sanitizer 配置。

返回值

无 (undefined)。

异常

TypeError

如果 options.sanitizer 传递了以下内容,则抛出此错误

描述

setHTML() 方法提供了一种 XSS 安全的方法,用于解析和清理 HTML 字符串并将其转换为 DocumentFragment,然后作为元素子树插入到 DOM 中。

setHTML() 会删除 HTML 输入字符串中在当前元素上下文中无效的任何元素,例如 <table> 外部的 <col> 元素。然后,它会删除 Sanitizer 配置不允许的任何 HTML 实体,并进一步删除任何 XSS 不安全的元素或属性——无论 Sanitizer 配置是否允许它们。

如果在 options.sanitizer 参数中没有指定 Sanitizer 配置,则 setHTML() 将使用默认的 Sanitizer 配置。此配置允许所有被认为是 XSS 安全的元素和属性,从而禁止被认为不安全的实体。可以指定自定义 Sanitizer 或 Sanitizer 配置来选择允许或删除哪些元素、属性和注释。请注意,即使 Sanitizer 配置允许不安全选项,在使用此方法时它们仍将被删除(该方法隐式调用 Sanitizer.removeUnsafe())。

对于将不受信任的 HTML 字符串插入到元素中,应使用 setHTML() 而非 Element.innerHTML。除非有允许不安全元素和属性的特殊需求,否则也应使用 setHTML() 而非 Element.setHTMLUnsafe()

请注意,由于此方法始终对 XSS 不安全实体的输入字符串进行清理,因此它不受 Trusted Types API 的保护或验证。

示例

基本用法

此示例展示了使用 setHTML() 清理和注入 HTML 字符串的一些方法。

js
// Define unsanitized string of HTML
const unsanitizedString = "abc <script>alert(1)<" + "/script> def";
// Get the target Element with id "target"
const target = document.getElementById("target");

// setHTML() with default sanitizer
target.setHTML(unsanitizedString);

// Define custom Sanitizer and use in setHTML()
// This allows only elements: div, p, button (script is unsafe and will be removed)
const sanitizer1 = new Sanitizer({
  elements: ["div", "p", "button", "script"],
});
target.setHTML(unsanitizedString, { sanitizer: sanitizer1 });

// Define custom SanitizerConfig within setHTML()
// This removes elements div, p, button, script, and any other unsafe elements/attributes
target.setHTML(unsanitizedString, {
  sanitizer: { removeElements: ["div", "p", "button", "script"] },
});

setHTML() 实时示例

此示例通过不同的 Sanitizer 调用该方法时提供了“实时”演示。代码定义了按钮,您可以单击它们分别使用默认和自定义 Sanitizer 清理和注入 HTML 字符串。原始字符串和清理后的 HTML 都已记录,以便您可以检查每种情况下的结果。

HTML

HTML 定义了两个 <button> 元素用于应用不同的 Sanitizer,另一个按钮用于重置示例,以及一个 <div> 元素用于注入字符串。

html
<button id="buttonDefault" type="button">Default</button>
<button id="buttonAllowScript" type="button">allowScript</button>

<button id="reload" type="button">Reload</button>
<div id="target">Original content of target element</div>

JavaScript

首先,我们定义要清理的字符串,所有情况下都相同。它包含 <script> 元素和 onclick 处理程序,两者都被认为是 XSS 不安全的。我们还定义了重新加载按钮的处理程序。

js
// Define unsafe string of HTML
const unsanitizedString = `
  <div>
    <p>This is a paragraph. <button onclick="alert('You clicked the button!')">Click me</button></p>
    <script src="path/to/a/module.js" type="module"><script>
  </div>
`;

const reload = document.querySelector("#reload");
reload.addEventListener("click", () => document.location.reload());

接下来,我们定义使用默认 Sanitizer 设置 HTML 的按钮的单击处理程序。这应该在插入 HTML 字符串之前剥离所有不安全的实体。请注意,您可以在 Sanitizer() 构造函数示例中准确查看删除了哪些元素。

js
const defaultSanitizerButton = document.querySelector("#buttonDefault");
defaultSanitizerButton.addEventListener("click", () => {
  // Set the content of the element using the default sanitizer
  target.setHTML(unsanitizedString);

  // Log HTML before sanitization and after being injected
  logElement.textContent =
    "Default sanitizer: remove script element and onclick attribute\n\n";
  log(`\nunsanitized: ${unsanitizedString}`);
  log(`\nsanitized: ${target.innerHTML}`);
});

下一个单击处理程序使用自定义 Sanitizer 设置目标 HTML,该 Sanitizer 仅允许 <div><p><script> 元素。请注意,因为我们使用的是 setHTML 方法,所以 <script> 也将被删除!

js
const allowScriptButton = document.querySelector("#buttonAllowScript");
allowScriptButton.addEventListener("click", () => {
  // Set the content of the element using a custom sanitizer
  const sanitizer1 = new Sanitizer({
    elements: ["div", "p", "script"],
  });
  target.setHTML(unsanitizedString, { sanitizer: sanitizer1 });

  // Log HTML before sanitization and after being injected
  logElement.textContent =
    "Sanitizer: {elements: ['div', 'p', 'script']}\n Script removed even though allowed\n";
  log(`\nunsanitized: ${unsanitizedString}`);
  log(`\nsanitized: ${target.innerHTML}`);
});

结果

单击“Default”和“allowScript”按钮,分别查看默认 Sanitizer 和自定义 Sanitizer 的效果。请注意,在这两种情况下,即使 Sanitizer 明确允许,<script> 元素和 onclick 处理程序都将被删除。

规范

规范
HTML Sanitizer API
# dom-element-sethtml

浏览器兼容性

另见