Beego默认防SQL注入,因其底层使用database/sql驱动并强制Raw()配合占位符(?)执行,天然隔离数据与指令;但若手动字符串拼接SQL或动态标识符未白名单校验,则防护失效。

Beego默认是否防SQL注入?
Beego在底层使用Go标准库database/sql驱动,并强制要求所有原生SQL操作通过Raw()配合占位符(?)执行,例如o.Raw("SELECT * FROM user WHERE id = ?", id)。这种设计天然隔离了数据与指令,只要不手动拼接字符串,就不可能触发SQL注入。
但注意:Beego的Raw()本身不校验SQL语法,如果你绕过占位符、用fmt.Sprintf或+拼接SQL再传给Raw(),防护就彻底失效。框架只管“怎么执行”,不管“你怎么造SQL”。
- ✅ 正确用法:
o.Raw("UPDATE user SET name = ? WHERE id = ?", name, id) - ❌ 危险写法:
o.Raw("UPDATE user SET name = '" + name + "' WHERE id = " + strconv.Itoa(id)) - ⚠️ 特别警惕第三方包封装的“便捷查询函数”,有些会暗中拼接SQL,需翻源码确认是否使用参数化
哪些Beego场景容易漏掉SQL注入防护?
不是所有数据库交互都走Raw()或ORM方法。最容易被忽略的是动态表名、字段名、ORDER BY子句、LIMIT偏移量等无法用占位符的位置。
比如你想按用户传入的sort参数排序:o.OrderBy("?" + sortParam)是无效的——占位符不能用于标识符。此时必须白名单校验:
- 只允许
sortParam为"created_at"、"name"、"score DESC"等预设值 - 禁止任何含空格、括号、点号、反引号的输入,否则直接拒绝
- 动态表名同理,
o.QueryTable("user_" + tenantId)必须确保tenantId只含小写字母和数字,且长度受限
Beego模板里插入JS时如何防XSS?
Beego基于html/template,默认对{{.JsCode}}做HTML转义,导致"变成"、变成,JS直接报错。这不是bug,是安全机制。
要让JS原样输出,必须在控制器中显式标记类型:
c.Data["JsCode"] = template.JS(jsString)
而不是:
c.Data["JsCode"] = jsString // ❌ 会被转义
常见错误场景:
- 从数据库读取一段初始化脚本(如
new Chart(...)),没包装template.JS就直接传入模板 - 用
strings.ReplaceAll动态拼JS字符串后忘记重新包装 - 误以为
{{raw .JsCode}}能绕过——Beego模板不支持raw这个函数,会报错
为什么开了Beego的XSS过滤器还不够?
Beego内置的XssFilter(通过HTMLEncoder.encode())只作用于HTTP请求参数,对Cookie、Header、JSON Body、数据库回写内容完全不处理。它只是第一道防线,不是终点。
真正危险的XSS往往来自“存储型”路径:用户提交富文本→存入MySQL→后台管理页渲染时未二次编码→管理员浏览器执行JS。这时候靠XssFilter毫无意义。
关键动作是分层控制:
- 入库前:对富文本用
bluemonday等库白名单过滤HTML标签 - 出库渲染时:根据上下文选择编码方式——HTML上下文用
html.EscapeString(),JS字符串内用js.EscapeString(),URL参数用url.PathEscape() - 前端加CSP头:
Content-Security-Policy: script-src 'self',阻断内联脚本执行
框架自动化的部分很薄,大部分防御责任仍在业务代码里——尤其是那些从数据库捞出来、又直接塞进innerHTML或eval()的地方,最容易被忽略。











