ShadowRoot: setHTML() 方法
ShadowRoot 介面的 setHTML() 方法提供了一種 XSS 安全的方法,可以將 HTML 字串解析和清理為 DocumentFragment,然後替換 Shadow DOM 中現有的樹。
語法
setHTML(input)
setHTML(input, options)
引數
input-
定義要清理和注入到 shadow root 中的 HTML 的字串。
options可選-
一個包含以下可選引數的 options 物件
sanitizer-
一個
Sanitizer或SanitizerConfig物件,它定義了輸入中允許或移除哪些元素,或者字串"default"用於預設的 sanitizer 配置。請注意,如果配置需要重用,通常Sanitizer比SanitizerConfig更高效。如果未指定,則使用預設的 sanitizer 配置。
返回值
無 (undefined)。
異常
TypeError-
如果
options.sanitizer傳遞了以下內容,則丟擲此錯誤- 非規範化的
SanitizerConfig(包含“允許”和“移除”配置設定)。 - 不具有值
"default"的字串。 - 不是
Sanitizer、SanitizerConfig或字串的值。
- 非規範化的
描述
setHTML() 方法提供了一種 XSS 安全的方法,可以解析和清理 HTML 字串,並使用它來替換 Shadow DOM 中現有的樹。
setHTML() 會移除 sanitizer 配置不允許的任何 HTML 實體,並進一步移除任何 XSS 不安全的元素或屬性——無論它們是否被 sanitizer 配置允許。
如果在 options.sanitizer 引數中未指定 sanitizer 配置,則 setHTML() 將使用預設的 Sanitizer 配置。此配置允許所有被認為是 XSS 安全的元素和屬性,從而禁止被認為不安全的實體。可以指定自定義 sanitizer 或 sanitizer 配置來選擇允許或移除哪些元素、屬性和註釋。請注意,即使 sanitizer 配置允許不安全選項,在使用此方法時(它隱式呼叫 Sanitizer.removeUnsafe()),它們仍會被移除。
在將不受信任的 HTML 字串插入 shadow DOM 時,應使用 setHTML() 代替 ShadowRoot.innerHTML。還應使用它代替 ShadowRoot.setHTMLUnsafe(),除非有特定需求需要允許不安全的元素和屬性。
請注意,由於此方法始終對 XSS 不安全實體的輸入字串進行清理,因此它不受 Trusted Types API 的保護或驗證。
示例
基本用法
此示例顯示了您可以使用 setHTML() 來清理和注入 HTML 字串的一些方法。
首先,我們將建立我們想要目標化的 ShadowRoot。這可以透過使用 Element.attachShadow() 以程式設計方式建立,但在此示例中,我們將以宣告方式建立 root。
<div id="host">
<template shadowrootmode="open">
<span>A span element in the shadow DOM</span>
</template>
</div>
我們可以像這樣從 #host 元素獲取 shadow root 的控制代碼
const shadow = document.querySelector("#host").shadowRoot;
以下程式碼顯示瞭如何使用字串和不同的 sanitizers 呼叫 setHTML() 來過濾並將 HTML 注入 shadow root。
// Define unsanitized string of HTML
const unsanitizedString = "abc <script>alert(1)<" + "/script> def";
// setHTML() with default sanitizer
shadow.setHTML(unsanitizedString);
// Define custom Sanitizer and use in setHTML()
// This allows only elements: <div>, <p>, <span> (<script> is unsafe and will be removed)
const sanitizer1 = new Sanitizer({ elements: ["div", "p", "span", "script"] });
shadow.setHTML(unsanitizedString, { sanitizer: sanitizer1 });
// Define custom SanitizerConfig within setHTML()
// This removes elements <div>, <p>, <span>, <script>, and any other unsafe elements/attributes
shadow.setHTML(unsanitizedString, {
sanitizer: { removeElements: ["div", "p", "span", "script"] },
});
setHTML() 即時示例
此示例提供了當使用不同 sanitizers 呼叫該方法時的“即時”演示。程式碼定義了您可以單擊的按鈕,分別使用預設 sanitizer 和自定義 sanitizer 來清理和注入 HTML 字串。原始字串和清理後的 HTML 會被記錄下來,以便您在每種情況下都可以檢查結果。
HTML
HTML 定義了兩個 <button> 元素用於應用不同的 sanitizers,另一個按鈕用於重置示例,以及一個包含宣告式 shadow root 的 <div>。
<button id="buttonDefault" type="button">Default</button>
<button id="buttonAllowScript" type="button">allowScript</button>
<button id="reload" type="button">Reload</button>
<div id="host">
<template shadowrootmode="open">
<span>I am in the shadow DOM </span>
</template>
</div>
JavaScript
首先,我們為重置按鈕定義處理程式。
const reload = document.querySelector("#reload");
reload.addEventListener("click", () => document.location.reload());
然後,我們定義要清理的字串,該字串將對所有情況都相同。它包含 <script> 元素和 onclick 處理程式,兩者都被認為是 XSS 不安全的。我們還獲取變數 shadow,它是我們對 shadow root 的控制代碼。
// Define unsafe string of HTML
const unsanitizedString = `
<div>
<p>Paragraph to inject into shadow DOM. <button onclick="alert('You clicked the button!')">Click me</button></p>
<script src="path/to/a/module.js" type="module"><script>
</div>
`;
const shadow = document.querySelector("#host").shadowRoot;
接下來,我們定義將 shadow root 設定為預設 sanitizer 的按鈕的點選處理程式。這應該在插入 HTML 字串之前剝離所有不安全的實體。請注意,您可以在 Sanitizer() 建構函式示例中確切地看到哪些元素被移除。
const defaultSanitizerButton = document.querySelector("#buttonDefault");
defaultSanitizerButton.addEventListener("click", () => {
// Set the content of the element using the default sanitizer
shadow.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: ${shadow.innerHTML}`);
});
下一個點選處理程式使用一個自定義 sanitizer 來設定目標 HTML,該 sanitizer 只允許 <div>、<p> 和 <script> 元素。請注意,因為我們使用的是 setHTML 方法,所以 <script> 也會被移除!
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"],
});
shadow.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: ${shadow.innerHTML}`);
});
結果
單擊“Default”和“allowScript”按鈕,分別檢視預設 sanitizer 和自定義 sanitizer 的效果。請注意,因為我們使用的是相同的 sanitization 方法,所以在這兩種情況下,<script> 元素和 onclick 處理程式都會被移除,即使它們被 sanitizer 顯式允許。
規範
| 規範 |
|---|
| HTML Sanitizer API # dom-shadowroot-sethtml |
瀏覽器相容性
載入中…