Beego防SQL注入第一道防线是ORM参数化机制而非中间件;中间件仅能做HTTP层字符过滤和请求拒绝,无法干预SQL构造过程,若Raw()中字符串拼接已发生,中间件无法拦截。

Beego 本身不靠中间件防 SQL 注入,而是靠 ORM 和 Raw() 的参数化查询机制;中间件能做的只是补漏——比如统一校验 URL 参数、表单字段是否含危险字符,但不能替代占位符。
为什么中间件不是防 SQL 注入的第一道防线
Beego 的 orm.Raw() 和 orm.QueryTable().Filter() 默认使用 ? 占位符,底层经 database/sql 驱动转义,只要你不拼接字符串(如 "SELECT * FROM user WHERE id = " + idStr),SQL 注入在 ORM 层就被截断了。中间件跑在 HTTP 层,它看不到 SQL 构造过程,也干预不了驱动行为。
- 你写
orm.Raw("SELECT * FROM user WHERE name = ?", name)→ 安全 - 你写
orm.Raw("SELECT * FROM user WHERE name = '" + name + "'")→ 中间件拦不住,运行时就炸 - 中间件即使检测出
name含UNION SELECT,也只能 Abort 请求,但错误已发生在 DB 层之外的拼接点
中间件能做的实际防护动作
它适合做「请求层清洗」和「快速拒绝」,尤其针对未走 ORM、直接调用 database/sql 或第三方库的场景:
- 对所有
GET查询参数(ctx.Input.Query("q"))和POST表单值(ctx.Input.ParseForm()后取c.Input.Data["post"]["field"])做基础字符过滤:拒绝含;、--、/*、UNION、SELECT(全大写/混合大小写)的值 - 对路径参数(如
/user/:id)提取后强制类型转换:id, _ := strconv.Atoi(ctx.Input.Param(":id")),非数字直接ctx.Abort(400, "Invalid ID") - 禁止在 URL 中传递原始 SQL 片段(如
?sql=...),注册到beego.BeforeRouter阶段统一拦截 - 注意:
beego.BeforeStatic不适用——静态资源不进 SQL 流程,加这层纯属冗余
容易踩的坑:把中间件当万能盾牌
常见错误是以为加个「防注入中间件」就高枕无忧,结果线上还是被扫出漏洞:
- 中间件里只检查
ctx.Input.Query(),却忘了ctx.Input.Header("X-Raw-SQL")这种自定义头可能带恶意 payload - 用
strings.Contains()检测UNION,但攻击者用unIoN绕过——应统一转大写再比对 - 在
beego.BeforeExec里做校验,但此时ctx.Input.ParseForm()可能已被 Controller 调用过一次,ctx.Request.Body已关闭,再读会 panic - 最致命的是:ORM 层用了
Raw()却传了未清洗的变量,中间件根本没机会介入——防御点错位了
真正关键的不是中间件写了什么,而是所有 SQL 构造点是否都坚持用占位符;中间件只是兜底,不是主力。一旦发现项目里存在字符串拼 SQL,优先重构 ORM 调用,而不是堆中间件逻辑。


















