DOMParser: parseFromString() 方法
警告:此方法將其輸入解析為 HTML,並將結果寫入 DOM。此類 API 被稱為 注入槽,如果輸入最初來自攻擊者,則可能成為 跨站點指令碼 (XSS) 攻擊的載體。
您可以透過始終傳遞 TrustedHTML 物件而不是字串並 強制執行可信型別 來緩解此風險。有關更多資訊,請參閱 安全注意事項。
DOMParser 介面的 parseFromString() 方法會解析包含 HTML 或 XML 的輸入,並返回一個 Document 物件,該物件的 contentType 屬性與 contentType 引數匹配。
注意: Document.parseHTMLUnsafe() 靜態方法提供了一種更簡潔的方式來將 HTML 標記解析為 Document 物件。
語法
parseFromString(input, mimeType)
引數
返回值
一個 Document 物件,其 contentType 與給定的 mimeType 匹配。
注意: 瀏覽器可能實際上返回一個 HTMLDocument 或 XMLDocument 物件。它們都繼承自 Document 且不新增任何屬性:它們本質上是等價的。
異常
TypeError-
當以下情況發生時會丟擲此異常:
mimeType的值不是 允許值 之一。- 當 Trusted Types 被 CSP 強制執行 且未定義預設策略時,向
input傳遞了字串值。
描述
parseFromString() 方法會解析包含 HTML 或 XML 的輸入,並返回一個 Document 物件,其 contentType 與 mimeType 匹配。這個 Document 包含一個完整的記憶體 DOM,該 DOM 與關聯頁面中的主文件是分開的。
如果 mimeType 是 text/html,則輸入將作為 HTML 解析,並且 <script> 元素將被標記為非可執行狀態,事件不會被觸發,內聯指令碼的事件處理程式也不會被呼叫。雖然文件可以下載 <iframe> 和 <img> 元素中指定的資源,但它本質上是惰性的。這很有用,因為您可以解析包含 宣告性 Shadow DOM 的 HTML 輸入,並在不影響可見頁面的情況下對文件執行操作。例如,您可以使用此方法清理輸入樹,並在需要時將輸入的部分注入到可見 DOM 中。
對於其他允許的值(text/xml、application/xml、application/xhtml+xml 和 image/svg+xml),輸入將作為 XML 解析。如果您想匯入 XML 檔案、驗證其結構並提取資料,這很有用。如果輸入不代表格式良好的 XML,則返回的文件將包含一個 <parsererror> 節點,描述解析錯誤的性質。
不允許的 mimeType 值會導致 TypeError 被丟擲。
安全注意事項
此方法將輸入解析到單獨的記憶體 DOM 中,停用任何 <script> 元素,並阻止事件處理程式執行。雖然返回的文件實際上是惰性的,但如果 DOM 中的事件處理程式和指令碼被插入到可見 DOM 中,它們將能夠執行。因此,該方法可能成為 跨站指令碼攻擊 (XSS) 的一個向量,在這種攻擊中,潛在不安全的輸入會先被解析到 Document 而未經清理,然後被注入到可見/活動 DOM 中,從而使程式碼能夠執行。
您應該透過始終傳遞 TrustedHTML 物件而不是字串,並使用 require-trusted-types-for CSP 指令強制執行受信任型別來降低此風險。這確保了輸入透過轉換函式,該函式有機會清理輸入以移除潛在危險的標記(例如 <script> 元素和事件處理程式屬性),然後才注入。
使用 TrustedHTML 可以僅在少數幾個地方審計和檢查清理程式碼是否有效,而不是分散在所有注入點。在使用 TrustedHTML 時,您通常不需要將清理程式傳遞給該方法。
請注意,即使您對可以執行程式碼的元素和屬性的輸入進行了清理,您在處理任何使用者輸入時仍需謹慎。例如,您的頁面可能會使用 XML 文件中的資料來獲取它隨後執行的檔案。
示例
使用 Trusted Types 解析輸入
在此示例中,我們將安全地解析潛在有害的 HTML 輸入,然後將其注入到可見頁面的 DOM 中。
為了減輕 XSS 風險,我們將從包含 HTML 的字串建立一個 TrustedHTML 物件。Trusted Types 尚未在所有瀏覽器中得到支援,因此我們首先定義 trusted types tinyfill。它充當 Trusted Types JavaScript API 的透明替代品。
if (typeof trustedTypes === "undefined")
trustedTypes = { createPolicy: (n, rules) => rules };
接下來,我們建立一個 TrustedTypePolicy,它定義了一個 createHTML() 方法,用於將輸入字串轉換為 TrustedHTML 例項。通常,createHTML() 的實現會使用像 DOMPurify 這樣的庫來清理輸入,如下所示。
const policy = trustedTypes.createPolicy("my-policy", {
createHTML: (input) => DOMPurify.sanitize(input),
});
然後,我們使用此 policy 物件從潛在不安全的輸入字串建立 TrustedHTML 物件,並將其解析為 Document。請注意,即使輸入不包含這些元素,生成的 Document 仍將表示一個包含根 <html>、<head> 和 <body> 的完整 HTML 文件。
// 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);
// Parse the TrustedHTML (which contains a trusted string)
const safeDocument = parser.parseFromString(trustedHTML, "text/html");
現在,safeDocument 包含一個根據我們的策略清理了有害元素的 DOM。下面,我們使用 Element.replaceWith() 將可見 DOM 的 body 替換為我們文件的 body:新 body 中的指令碼將執行,事件處理程式觸發時程式碼也將執行。
document.body.replaceWith(safeDocument.body);
解析 XML、SVG 和 HTML
下面的程式碼展示瞭如何使用該方法解析每種內容型別。雖然在實際程式碼中應使用 Trusted Types,但此處為簡潔起見省略了它們。
const parser = new DOMParser();
const xmlString = "<warning>Beware of the tiger</warning>";
const doc1 = parser.parseFromString(xmlString, "application/xml");
console.log(doc1.contentType); // "application/xml"
const svgString = '<circle cx="50" cy="50" r="50"/>';
const doc2 = parser.parseFromString(svgString, "image/svg+xml");
console.log(doc2.contentType); // "image/svg+xml"
const htmlString = "<strong>Beware of the leopard</strong>";
const doc3 = parser.parseFromString(htmlString, "text/html");
console.log(doc3.contentType); // "text/html"
console.log(doc1.documentElement.textContent);
// "Beware of the tiger"
console.log(doc2.firstChild.tagName);
// "circle"
console.log(doc3.body.firstChild.textContent);
// "Beware of the leopard"
請注意,上面的 application/xml 和 image/svg+xml MIME 型別在功能上是相同的——後者不包含任何 SVG 特定解析規則。
錯誤處理
當使用 XML 解析器處理不代表格式良好 XML 的字串時,parseFromString 返回的 XMLDocument 將包含一個 <parsererror> 節點,描述解析錯誤的性質。
const parser = new DOMParser();
const xmlString = "<warning>Beware of the missing closing tag";
const doc = parser.parseFromString(xmlString, "application/xml");
const errorNode = doc.querySelector("parsererror");
if (errorNode) {
// parsing failed
} else {
// parsing succeeded
}
此外,解析錯誤可能會報告到瀏覽器的 JavaScript 控制檯。
規範
| 規範 |
|---|
| HTML # dom-domparser-parsefromstring-dev |
瀏覽器相容性
載入中…
另見
XMLSerializerJSON.parse()-JSON文件的對應方法。