正则过滤无法防御XSS,必须用HTML解析器白名单清洗;HtmlSanitizer是C#最可靠的方案,自动剥离事件属性和危险协议,而HtmlAgilityPack仅适合解析非安全场景。
别用正则删做 XSS 防御——它根本拦不住这类 payload。
真正防 XSS 的清洗,必须基于 HTML 解析器做白名单控制,而不是字符串替换。
HtmlSanitizer 是目前 C# 里最靠谱的 XSS 防御库
它不是“去标签”,而是按规则保留安全子集:默认只放行
、
、
(且自动过滤
中的
)、
(且校验
协议),所有事件属性(
、
等)和危险协议(
、
)一律剥离。
安装:
基础用法:
立即学习
“
前端免费学习笔记(深入)
”;
关键点:
默认不放行
、
、
、
—— 不用额外写规则
自动解码并重编码属性值,防止双写编码绕过(如
)
对
会清空
值,不是简单删标签
为什么 HtmlAgilityPack 不适合防 XSS
是解析/清洗工具,不是安全 sanitizer。它能帮你取
或删标签,但无法识别语义风险:
C知道
CSDN推出的一款AI技术问答工具
下载
它不会拦截
<.*?>hrefjavascript:srconloadonclickdata:vbscript:Install-Package HtmlSanitizervar sanitizer = new HtmlSanitizer();
sanitizer.AllowedTags.Add("article"); // 手动加允许标签
sanitizer.AllowedAttributes.Add("cite"); // 允许 cite 属性
string clean = sanitizer.Sanitize(dirtyHtml);javascript:hrefHtmlAgilityPackInnerText
—— 这仍是合法 HTML
它不会校验
这种内联 SVG XSS
它默认不处理 CSS 表达式(
expression(...)
)或 IE 条件注释
如果你只是“提取纯文本展示”,用
HtmlAgilityPack
没问题;但只要输出到页面(
innerHTML
、
@Html.Raw()
),就必须换
HtmlSanitizer
。
Regex.Replace 清洗在什么场景下还能用
仅限可信来源、结构极简、且不参与 DOM 渲染的场合,比如日志摘要、后台字段预览:
已知只有
、
、
,无属性、无嵌套
必须提前移除注释:
Regex.Replace(html, @"", "")
必须禁用贪婪匹配:
Regex.Replace(html, @"<[^>]*>", "", RegexOptions.Singleline)
不能处理
或
这类现代 HTML5 标签
一旦输入来自用户编辑器、富文本粘贴、或第三方 API,regex 就该退役了。
容易被忽略的细节:编码 + BOM + 多层嵌套实体
真实数据常带干扰:
双重 HTML 实体:
→ 必须先
WebUtility.HtmlDecode
两次,再进
HtmlSanitizer
UTF-8 BOM(
\uFEFF
)会导致
HtmlSanitizer
解析失败,报错
Unexpected token
→ 读取时用
new StreamReader(stream, Encoding.UTF8, detectEncodingFromByteOrderMarks: true)
Word 粘贴内容含大量
mso-*
样式和冗余
标签 →
HtmlSanitizer
默认不清理这些,需配合
AllowedCssProperties.Clear()
和自定义
CssClassWhitelist
清洗不是一步到位的动作,而是按数据来源分层:先解码,再 BOM 处理,再 sanitizer,最后才是业务逻辑裁剪。
