,
並支援屬性過濾
需求:驗證使用者輸入的 HTML 字串,**僅允許 ``, ``, ``, `
`, `),但非白名單標籤即使帶屬性也禁止。使用**否定前瞻**正則實現精準攔截。 合法 正則無法完美檢查標籤巢狀閉合 (如 ``)。生產環境建議**結合 DOMParser 驗證結構 + 正則過濾標籤白名單**: `。 JS 限制 HTML 標籤白名單:**正則否定前瞻快速攔截非法標籤 + DOMParser 驗證結構 + DOMPurify 徹底淨化屬性**。三層防護確保使用者生成內容安全、合規、結構完整。
` 五種標籤**,其他標籤 (如 ``, ``) 視為非法。且允許白名單標籤帶屬性 (如 `核心正則邏輯
// 正則:匹配「非白名單標籤」
// 白名單:i, b, u, p, br (含自閉合
)
const forbiddenTagRegex = /<(?!(?:\/?(?:i|b|u|p|br))[\s/>])[^>]*>/i;
// 測試
const str1 = '1213456'; // 含非法
const str2 = '123
'; // 僅合法
const str3 = '正則詳細拆解
片段 含義 `<` 匹配標籤開頭 `<` `(?!` **否定前瞻**:斷言後面**不匹配**括號內模式 `\/?` 可選的 `/` (匹配結束標籤 ``) `(?:i|b|u|p|br)` 白名單標籤名 (非捕獲組) `[\s/>]` 標籤名後必須跟空白、`>` 或 `/>` (確保完整匹配標籤名,避免誤匹配 `` 為 ` )`[^>]*>` 前瞻失敗 (即非白名單標籤) 時,匹配直到 `>` 的完整標籤 `i` (flag) 忽略大小寫 完整驗證函數 (含標籤閉合檢查)
function validateHtmlWhitelist(html) {
// 1. 正則快速檢查非法標籤
const forbiddenTagRegex = /<(?!(?:\/?(?:i|b|u|p|br))[\s/>])[^>]*>/i;
if (forbiddenTagRegex.test(html)) {
return {valid: false, reason: '包含非白名單標籤'};
}
// 2. DOMParser 驗證結構合法性 (瀏覽器環境)
try {
const parser = new DOMParser();
const doc = parser.parseFromString(html, 'text/html');
// 檢查解析錯誤
if (doc.querySelector('parsererror')) {
return {valid: false, reason: 'HTML 結構錯誤 (標籤未閉合/巢狀錯誤)'};
}
// 可選:進一步遍歷所有元素再次確認標籤名
const allElements = doc.body.getElementsByTagName('*');
const allowed = new Set(['i', 'b', 'u', 'p', 'br']);
for (let el of allElements) {
if (!allowed.has(el.tagName.toLowerCase())) {
return {valid: false, reason: `發現非白名單標籤: <${el.tagName}>`};
}
}
return {valid: true, sanitized: doc.body.innerHTML};
} catch (e) {
return {valid: false, reason: '解析異常: ' + e.message};
}
}
// Node.js 環境可用 'xmldom' 或 'jsdom' 替代 DOMParser
安全性補充:XSS 防護
import DOMPurify from 'dompurify';
const clean = DOMPurify.sanitize(html, {
ALLOWED_TAGS: ['i', 'b', 'u', 'p', 'br'],
ALLOWED_ATTR: ['style', 'class', 'id']
});
總結