處理使用者輸入的 HTML 內容時,需移除腳本、危險標籤與實體編碼,防止 XSS 攻擊。本文提供兩個互補的靜態方法:完全移除所有標籤(純文字輸出)與保留安全標籤、移除危險標籤(富文本輸出)。
public static string GetNoHTMLString(string html)
{
if (string.IsNullOrEmpty(html)) return "";
// 1. 移除 ", "", RegexOptions.IgnoreCase | RegexOptions.Singleline);
// 2. 移除所有 HTML 標籤
html = Regex.Replace(html, @"<[^>]+>", "", RegexOptions.IgnoreCase);
// 3. 移除註解
html = Regex.Replace(html, @"", "", RegexOptions.Singleline);
// 4. 解碼常見實體
html = Regex.Replace(html, @"&(quot|#34);", "\"", RegexOptions.IgnoreCase);
html = Regex.Replace(html, @"&(amp|#38);", "&", RegexOptions.IgnoreCase);
html = Regex.Replace(html, @"&(lt|#60);", "<", RegexOptions.IgnoreCase);
html = Regex.Replace(html, @"&(gt|#62);", ">", RegexOptions.IgnoreCase);
html = Regex.Replace(html, @"&(nbsp|#160);", " ", RegexOptions.IgnoreCase);
html = Regex.Replace(html, @"&(iexcl|#161);", "\u00A1", RegexOptions.IgnoreCase);
html = Regex.Replace(html, @"&(cent|#162);", "\u00A2", RegexOptions.IgnoreCase);
html = Regex.Replace(html, @"&(pound|#163);", "\u00A3", RegexOptions.IgnoreCase);
html = Regex.Replace(html, @"&(copy|#169);", "\u00A9", RegexOptions.IgnoreCase);
// 5. 移除數字實體 數字;
html = Regex.Replace(html, @"\d+;", "", RegexOptions.IgnoreCase);
// 6. 清理空白與編碼
html = html.Replace("<", "").Replace(">", "").Replace("\r\n", "");
return HttpContext.Current.Server.HtmlEncode(html).Trim();
}
public static string GetSafeHTMLString(string html)
{
if (string.IsNullOrEmpty(html)) return "";
// 定義需完整移除的危險標籤(含內容)
string[] dangerousTags = {
"applet", "body", "embed", "frame", "script", "frameset",
"html", "iframe", "style", "layer", "link", "ilayer",
"meta", "object"
};
foreach (string tag in dangerousTags)
{
// 移除 ... 完整區塊
string pattern = $@"<{tag}[^>]*>.*?{tag}>";
html = Regex.Replace(html, pattern, "", RegexOptions.IgnoreCase | RegexOptions.Singleline);
// 移除單獨的開啟/關閉標籤(無內容者)
html = Regex.Replace(html, $@"?{tag}[^>]*>", "", RegexOptions.IgnoreCase);
}
// 可選:移除事件屬性 onclick, onload, onerror 等
html = Regex.Replace(html, @"\s+(on\w+)\s*=\s*[""'][^""']*[""']", "", RegexOptions.IgnoreCase);
// 可選:移除 javascript: 協定連結
html = Regex.Replace(html, @"href\s*=\s*[""']\s*javascript:[^""']*[""']", "", RegexOptions.IgnoreCase);
return html;
}
| 情境 | 建議方法 | 說明 |
|---|---|---|
| 搜尋關鍵字、摘要顯示、匯出純文字 | GetNoHTMLString | 徹底移除所有標籤與實體,輸出安全純文字 |
| 論壇發文、部落格內容、CMS 富文本欄位 | GetSafeHTMLString | 保留 <b>, <p>, <img> 等排版標籤,移除腳本與結構破壞標籤 |
| 使用者輸入即時預覽 | 先 GetSafeHTMLString 再前端渲染 | 雙重防護:後端淨化 + 前端 DOMPurify |
手寫 Regex 難以覆蓋所有繞過技巧(如編碼混淆、標籤嵌套異常)。生產環境強烈建議使用:
Encoder.HtmlEncode, GetSafeHtmlFragment。// HtmlSanitizer 使用範例
var sanitizer = new HtmlSanitizer();
sanitizer.AllowedTags.Add("img");
sanitizer.AllowedAttributes.Add("src");
string safe = sanitizer.Sanitize(userInput);