html/template比text/template安全,因为它在.Execute时自动进行上下文感知转义,如HTML内容中转义<为<、属性中URL编码、JS字符串中转义引号等,而text/template完全不转义,仅做原始字符串替换。

直接说结论:Golang微服务的安全防线不在框架自动补丁里,而在每个输入点的上下文校验和每个输出点的编码策略中。你写的http.HandlerFunc、中间件、模板渲染、SQL查询,只要接触了用户输入,就可能成为XSS、SQL注入或路径遍历的入口——没有例外。
html/template 为什么比 text/template 安全?
因为html/template在执行.Execute时,会根据上下文自动转义:变成<code><,"变成",javascript:协议被剥离。而text/template只做纯文本替换,把{{.UserInput}}原样吐出去,浏览器一解析就执行脚本。
- 必须用
html/template加载所有含用户数据的HTML模板,哪怕只是渲染一个用户名 - 如果真要输出原始HTML(如富文本编辑器内容),先用
bluemonday净化,再显式转为template.HTML,不能靠“信任来源”绕过 - 注意:
template.URL、template.JS等类型只在对应上下文生效,乱用template.HTML等于主动开后门
database/sql 参数化查询怎么写才真正防注入?
核心是“参数不参与SQL字符串拼接”。只要出现fmt.Sprintf("SELECT * FROM users WHERE name = '%s'", name)或db.Query("SELECT * FROM users WHERE id = " + id),就已失效。
- 正确写法只有两种:
db.Query("SELECT * FROM users WHERE id = ?", id)或stmt, _ := db.Prepare("..."); stmt.Query(id) - GORM默认安全,但一旦调用
Raw()或Exec()传入拼接字符串,防护立刻失效 - ID类字段建议用
strconv.Atoi先转整型,非数字直接http.Error拒绝,别依赖数据库层兜底
中间件里哪些地方最容易漏掉XSS/注入?
中间件常被当成“辅助逻辑”,但它是每个请求必经之路。日志、限流、IP解析、Header读取,全是高危区。
Go 配置库,使用 spf13/viper — 分层优先级(flag > env >file > KV > default),提供 BindPFlag/BindPFlags、SetEnvPrefix + SetEnvKeyReplace 等功能。
立即学习“go语言免费学习笔记(深入)”;
-
c.Request.Header.Get("X-Forwarded-For")直接写进日志?攻击者可注入\n<script>alert(1)</script>污染日志系统甚至前端展示页 - 用
c.Param("id")生成限流键?没校验是否为数字,可能被构造为../../etc/passwd%00触发路径遍历 - 从
Cookie取值做路由判断?未用http.SameSiteStrictMode且没清理特殊字符,CSRF+XSS可联动利用
Content-Security-Policy 头设错反而更危险
不是加了CSP就安全,策略宽松或冲突会形同虚设,甚至干扰正常功能。
-
default-src 'self'是起点,但若页面含内联JS(<script>init();</script>),必须加'unsafe-inline'——这会削弱防护,应优先改造成外部脚本 -
script-src 'self' https://cdn.example.com比script-src *严格得多,但漏掉https://apis.google.com会导致OAuth失败 - 设置顺序很重要:
X-Content-Type-Options: nosniff必须存在,否则浏览器可能忽略CSP;Content-Security-Policy头不能被后续中间件覆盖
最易被忽略的其实是“动态上下文”:同一个用户输入,在JSON响应里要走json.Marshal,在HTML里要走html/template,在SQL里要走参数化查询,三者转义规则完全不同。拿错上下文,就是拿刀递给别人。

















