Element:innerHTML 屬性

Baseline 廣泛可用 *

此特性已相當成熟,可在許多裝置和瀏覽器版本上使用。自 ⁨2015 年 7 月⁩以來,各瀏覽器均已提供此特性。

* 此特性的某些部分可能存在不同級別的支援。

警告:此屬性將輸入解析為 HTML,並將結果寫入 DOM。像這樣的 API 被稱為注入槽,如果輸入最初來自攻擊者,它們可能是跨站指令碼(XSS)攻擊的潛在途徑。

您可以透過始終分配 TrustedHTML 物件而不是字串並強制執行可信型別來減輕這種風險。有關更多資訊,請參閱安全注意事項

Element 介面的 innerHTML 屬性用於獲取或設定元素中包含的 HTML 或 XML 標記,這兩種情況下都省略任何影子根

要將 HTML 插入到文件中,而不是替換元素的內容,請使用方法insertAdjacentHTML()

獲取該屬性會返回一個字串,其中包含元素後代的 HTML 序列化。

設定該屬性接受TrustedHTML 物件或字串。它會將此值解析為 HTML,並用結果替換所有元素的後代。當設定為 null 值時,該 null 值將轉換為空字串(""),因此 elt.innerHTML = null 等同於 elt.innerHTML = ""

異常

SyntaxError DOMException

如果嘗試使用格式不正確的 HTML 字串設定 innerHTML 的值,則丟擲此錯誤。

TypeError

如果在可信型別CSP 強制執行且未定義預設策略時將屬性設定為字串,則丟擲此錯誤。

NoModificationAllowedError DOMException

如果嘗試將 HTML 插入到其父級為Document的節點中,則丟擲此錯誤。

描述

innerHTML 獲取元素內巢狀子 DOM 元素的序列化,或設定應解析為替換元素內 DOM 樹的 HTML 或 XML。

請注意,當 <> 字元出現在屬性值中時,某些瀏覽器會將其序列化為 &lt;&gt;(請參閱瀏覽器相容性)。這是為了防止潛在的安全漏洞(變異 XSS),其中攻擊者可以精心構造繞過淨化函式的輸入,從而實現跨站指令碼(XSS)攻擊。

影子 DOM 考慮

從屬性讀取的 DOM 樹的序列化不包括影子根——如果您想獲取包含影子根的 HTML 字串,則必須改用Element.getHTML()ShadowRoot.getHTML() 方法。

同樣,當使用 innerHTML 設定元素內容時,HTML 字串會被解析為不包含影子根的 DOM 元素。因此,例如,<template> 會被解析為 HTMLTemplateElement,無論是否指定了shadowrootmode 屬性。為了從包含宣告性影子根的 HTML 字串設定元素內容,您必須改用 Element.setHTMLUnsafe()ShadowRoot.setHTMLUnsafe()

安全注意事項

innerHTML 屬性可能是跨站指令碼(XSS)攻擊最常見的載體,其中使用者提供的潛在不安全字串在未首先進行淨化的情況下被注入到 DOM 中。雖然該屬性確實阻止了<script> 元素在注入時執行,但它容易受到攻擊者可以精心構造 HTML 來執行惡意 JavaScript 的許多其他方式的影響。例如,以下示例將執行 error 事件處理程式中的程式碼,因為 <img>src 值不是有效的影像 URL。

js
const name = "<img src='x' onerror='alert(1)'>";
el.innerHTML = name; // shows the alert

您可以透過始終分配TrustedHTML 物件而不是字串,並使用require-trusted-types-for CSP 指令強制執行可信型別來緩解這些問題。這確保了輸入透過一個轉換函式,該函式有機會在注入之前淨化輸入以刪除潛在危險的標記。

注意:當您知道使用者提供的內容應該是純文字時,應使用Node.textContent。這可以防止它被解析為 HTML。

示例

讀取元素的 HTML 內容

讀取 innerHTML 會導致使用者代理序列化元素的後代。

給定以下 HTML

html
<div id="example">
  <p>My name is Joe</p>
</div>

您可以獲取並記錄外部<div>內容標記,如下所示:

js
const myElement = document.querySelector("#example");
const contents = myElement.innerHTML;
console.log(contents); // "\n  <p>My name is Joe</p>\n"

替換元素的內容

在此示例中,我們將透過將 HTML 分配給元素的 innerHTML 屬性來替換元素的 DOM。為了減輕 XSS 的風險,我們將首先從包含 HTML 的字串建立一個 TrustedHTML 物件,然後將該物件分配給 innerHTML

可信型別尚未在所有瀏覽器中受支援,因此我們首先定義可信型別小型填充。這可以作為可信型別 JavaScript API 的透明替代品。

js
if (typeof trustedTypes === "undefined")
  trustedTypes = { createPolicy: (n, rules) => rules };

接下來,我們建立一個 TrustedTypePolicy,它定義了一個 createHTML(),用於將輸入字串轉換為 TrustedHTML 例項。通常,createHTML() 的實現使用像 DOMPurify 這樣的庫來清理輸入,如下所示

js
const policy = trustedTypes.createPolicy("my-policy", {
  createHTML: (input) => DOMPurify.sanitize(input),
});

然後我們使用這個 policy 物件從潛在不安全的輸入字串建立 TrustedHTML 物件,並將結果分配給元素。

js
// The potentially malicious string
const untrustedString = "<p>I might be XSS</p><img src='x' onerror='alert(1)'>";

// Create a TrustedHTML instance using the policy
const trustedHTML = policy.createHTML(untrustedString);

// Inject the TrustedHTML (which contains a trusted string)
const element = document.querySelector("#container");
element.innerHTML = trustedHTML;

警告:雖然您可以直接將字串分配給 innerHTML,但如果要插入的字串可能包含潛在的惡意內容,這會帶來安全風險。您應該使用 TrustedHTML 來確保內容在插入之前被淨化,並且您應該設定 CSP 頭部以強制執行可信型別

規範

規範
HTML
# dom-element-innerhtml

瀏覽器相容性

另見