不能用正则删html标签,因无法处理嵌套、大小写混用、实体编码等,易漏掉onerror、javascript:等危险载荷;应先用bluemonday白名单过滤,再用html2text转纯文本。

直接用正则删标签是错的,尤其当富文本含嵌套、大小写混用或实体编码时,regexp 会漏掉 onerror、javascript:、<script></script> 这类绕过载荷,还可能破坏文本结构。真正安全的做法是:先白名单过滤 HTML,再转纯文本——不是“删标签”,而是“解析 + 安全降级”。
为什么不能用 strings.Replace 或简单 regexp 去 HTML 标签
正则匹配 \]+\> 看似简单,但实际踩坑非常多:
- 无法识别注释
<!-- ... -->、CDATA 段、自闭合标签(如<br>) - 遇到
<img src="x" onerror="alert(1)">,删完标签后只剩空格,但原始危险属性已进入文本流 - 大小写混用(
<script></script>)、编码绕过(<script>)完全逃逸 - 不处理 HTML 实体(
、©),输出乱码或空白 - 破坏语义结构:把
<h2>标题</h2> <p>正文</p>变成“标题正文”,丢失换行和段落分隔
正确路径:bluemonday → html2text
标准流程是两步:先用 bluemonday 白名单净化 HTML,再用 html2text 转为结构化纯文本。二者配合才能兼顾安全与可读性。
安装依赖:
go get github.com/microcosm-cc/bluemonday<br>go get github.com/gh-mirrors/html2t/html2text
实操要点:
-
bluemonday.UGCPolicy()允许常见富文本标签(<p></p>、<strong></strong>、<a></a>、<code>等),自动剥离 script/style/on\* 属性 - 过滤后仍需传给
html2text.FromString(),而不是直接strings.TrimSpace—— 后者不识别块级元素换行、列表缩进、链接文本提取等 - 若只需前 N 字符(如摘要截取),应在
html2text输出后再截断,而非在 HTML 字符串上截 —— 否则可能切在标签中间,导致bluemonday解析失败
常见误用:template.HTML + html.UnescapeString 组合
有人把用户提交的 HTML 先 html.UnescapeString,再 template.HTML(...),最后塞进模板里显示 —— 这等于主动打开 XSS 通道。
原因很直接:
-
html.UnescapeString是解码函数,不是过滤器;它把<变回,反而让恶意标签复活 -
template.HTML是信任标记,不是消毒开关;它跳过所有转义,原样输出 - 两者叠加 = 把已编码的危险内容还原 + 强制执行,比直接拼接还危险
正确做法是:任何不可信 HTML 都必须经过 bluemonday 过滤,且只在过滤后才考虑 template.HTML;纯文本场景一律走 html2text,不碰 template.HTML。
最易被忽略的一点:bluemonday 的 Policy 配置必须显式启用你需要的标签和属性,比如要保留链接,得调用 AllowAttrs("href").OnElements("a");默认 UGCPolicy 不允许 target 或 rel,别假设它“够用”。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











