
Go 的 html/template 包默认会对变量插值进行 HTML 转义,以防止 XSS 攻击;当从 PostgreSQL 读取含 HTML 标签的富文本(如 Argentine Army)并直接渲染时,尖括号会被转义为 <b>。解决方法是显式将字符串标记为可信 HTML,而非禁用转义机制。
Go 的 `html/template` 包默认会对变量插值进行 HTML 转义,以防止 XSS 攻击;当从 PostgreSQL 读取含 HTML 标签的富文本(如 `Argentine Army`)并直接渲染时,尖括号会被转义为 ``。解决方法是显式将字符串标记为可信 HTML,而非禁用转义机制。
在 Go Web 开发中,html/template 是安全优先的设计:所有通过 {{.Content}} 插入的字符串都会被自动转义(例如 问题本质并非 PostgreSQL 或数据库驱动导致,而是模板引擎的默认行为。你存储的 The Argentine Army is 在数据库和 Go 变量中始终是原始字符串;转义仅发生在模板渲染阶段。
✅ 正确解决方案:使用 template.HTML 类型显式声明内容为“已信任的 HTML”
你需要在模板上下文中注册一个安全转换函数,例如:
立即学习“前端免费学习笔记(深入)”;
func unsafeHTML(s string) template.HTML {
return template.HTML(s)
}然后在 Echo 初始化模板时注入该函数:
// 创建模板函数映射
funcMap := template.FuncMap{
"unsafe": unsafeHTML,
}
// 解析模板(假设使用 html/template)
t := template.Must(template.New("").Funcs(funcMap).ParseGlob("templates/*.html"))
e.Renderer = &TemplateRenderer{Template: t}接着,在你的模板 onlytestingtpl.html 中,使用自定义函数绕过转义:
<!-- 错误:会被转义 -->
<div>{{.Content}}</div>
<!-- 正确:显式标记为可信 HTML -->
<div>{{.Content | unsafe}}</div>⚠️ 重要注意事项:
绝不滥用:仅对完全可控、已过滤或可信来源的 HTML 使用 template.HTML。若 content 来自用户输入且未经服务端净化(如使用 bluemonday 库),直接 unsafe 将引入严重 XSS 风险。
-
替代方案(推荐用于用户内容):
若需渲染用户提交的富文本,应先在后端做白名单过滤(例如只允许等安全标签),再转换为 template.HTML。示例:
import "github.com/microcosm-cc/bluemonday" policy := bluemonday.UGCPolicy() // 默认允许常见富文本标签 cleanHTML := policy.Sanitize(b.Content) b.Content = cleanHTML // 再传入模板
不要改用 text/template:它不提供 HTML 转义保护,会全局削弱安全性,属于错误规避而非正确解法。
总结:Go 模板的自动转义是安全特性而非 bug。通过 template.HTML 类型 + 显式函数封装(如 unsafe),可在保障整体安全的前提下,精准控制特定字段的原始 HTML 渲染。关键原则是——信任但验证,转义但可选,安全不妥协。











