go模板防xss需用html/template而非text/template,变量自动html转义;输出原始html须显式用template.html且仅限可信内容;json接口禁用模板,应使用json.marshal;csp替代已废弃的x-xss-protection。

Go模板里怎么自动转义HTML
Go的html/template包默认就防XSS,关键在于别误用text/template——它不转义,直接拼字符串。
常见错误是写func(w http.ResponseWriter, r *http.Request) { t := template.Must(template.New("").Parse(...)) },没指定html/template,结果用户输入的<script>alert(1)</script>原样输出。
- 必须用
html/template:import "html/template",不是"text/template" - 模板变量用
{{.Name}}时,只要数据来自template.Execute传入的结构体字段,就会自动HTML转义 - 如果真要输出原始HTML(比如富文本内容),得显式调用
template.HTML包装,且仅限可信来源
用户输入进模板前要不要预处理
不需要、也不该在存入数据库或传给模板前“手动过滤标签”。Go模板的转义机制是上下文感知的——它知道你是在HTML元素内、属性里、JS字符串中还是CSS里,会按需转义,比正则清洗靠谱得多。
容易踩的坑是:有人用strings.ReplaceAll(input, "这类方式“消毒”,结果反而破坏了模板的上下文转义逻辑,还可能漏掉<code>onerror="..."这种事件属性里的JS执行点。
- 信任模板引擎:把原始用户输入直接传给
Execute,让它干活 - 禁止对输入做HTML标签移除、白名单过滤等操作——这既多余又危险
- 唯一例外:前端富文本编辑器提交的内容,后端应限制只允许
template.HTML渲染,且必须经过去除危险属性(如javascript:协议)的专用净化库,比如bluemonday
HTTP响应头里加X-XSS-Protection还有用吗
基本没用了。Chrome 78+、Firefox 76+、Edge 80+ 都已弃用X-XSS-Protection,设了也无效;Safari从没支持过。现代浏览器靠CSP和内置的反射XSS拦截器,不是靠这个header。
现在真正该配的是Content-Security-Policy,尤其是script-src 'self'这类限制,能拦住大部分内联脚本和eval类攻击。
- 删掉
w.Header().Set("X-XSS-Protection", "1; mode=block")这类代码 - 如果项目需要兼容老IE(极少见),可保留,但别指望它起作用
- CSP header要配合
html/template一起用——模板负责防注入,CSP兜底防执行
JSON接口返回用户数据会触发XSS吗
不会,前提是返回的是纯JSON,且前端用JSON.parse()而不是innerHTML = ...或eval()去处理。但Go里一个典型陷阱是:用html/template渲染JSON响应体。
比如写t := template.Must(html.New("json").Parse(`{"name": "{{.Name}}"}`)),这就错了——html/template会把{{.Name}}当HTML上下文转义,而JSON里需要的是JSON字符串转义(比如双引号变\",斜杠变\/),结果生成非法JSON或被绕过。
- JSON接口一律用
json.Marshal,别走模板 - 如果非要用模板(极少数场景),改用
text/template+ 手动js.EscapeString(来自"html/template"包)处理字段 - 永远检查响应Content-Type是不是
application/json,不是就可能被浏览器当作HTML解析
最常被忽略的一点:模板转义只对Execute传入的数据生效。如果在模板里调用自定义函数返回template.HTML,或者用template.JS、template.CSS等类型,就等于主动关闭防护——这些类型必须确保内容100%可信,否则XSS立刻复现。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











