<p>防范SQL注入最有效方式是使用参数化查询(如db.Query("SELECT * FROM users WHERE name = ?", name)),严禁字符串拼接;对无法参数化的表名、排序字段等须严格白名单校验;ORM或查询构建器仍需正确使用,避免手写拼接。</p>

用 db.Query 或 db.Prepare 代替字符串拼接
SQL 注入最常见来源就是把用户输入直接拼进 SQL 字符串里,比如 db.Query("SELECT * FROM users WHERE name = '" + name + "'")。Fiber 本身不干预这个过程,它只负责把请求交给你的 handler,后续全靠你写法是否安全。
- 必须改用参数化查询:
db.Query("SELECT * FROM users WHERE name = ?", name) - 高频或复杂查询建议预编译:
stmt, _ := db.Prepare("INSERT INTO logs (msg) VALUES (?)"),再用stmt.Exec(msg) - 切勿对用户输入做“简单过滤”(如替换单引号),攻击者绕过方式太多,参数化是唯一可靠防线
避免在 fiber.Ctx 中信任未经校验的参数
Fiber 的 c.Params、c.Query、c.Body 全部来自客户端,没有任何默认过滤或类型约束。一个 c.Query("id") 返回的是原始字符串,哪怕你期望它是数字,也得自己转并校验范围。
- 路径参数:
id := c.Params("id")→ 必须用strconv.Atoi(id)转换,并检查错误;不能直接塞进 SQL - JSON body:
var req struct{ ID int };→ 用c.BodyParser(&req)借助结构体标签做基础类型约束,但 ID 仍需业务层校验(如是否 > 0) - 特别警惕
c.FormValue和c.Get(Header),它们返回的字符串同样不可信
ORM 或查询构建器不是免检通行证
用 GORM、SQLX 或 Squirrel 并不自动防注入。问题出在“怎么用”,而不是“用了没”。例如 GORM 的 Where("name = " + name) 和原生拼接一样危险;Squirrel 的 PlaceholderFormat 若被手动绕过也会失效。
- GORM 安全写法:
db.Where("name = ?", name).Find(&user),而非Where("name = '" + name + "'") - SQLX 推荐用
sqlx.Named配合命名参数,避免位置错位导致逻辑错乱 - 所有构建器最终生成的 SQL 都应日志抽查——尤其带
IN (?)或动态字段名时,极易漏掉白名单校验
数据库连接与上下文隔离要匹配 Fiber 生命周期
Fiber 是无状态 HTTP 分发器,但你的 DB 连接池和事务管理必须跟上协程语义。如果多个请求共用一个未隔离的 *sql.Tx,或在 Fiber 挂起后继续用已失效的连接,轻则报错,重则数据混写。
- 每个请求应独占事务:
tx, _ := db.BeginTx(c.Context(), nil),并在 defer 中tx.Commit()或tx.Rollback() - 避免在中间件中创建全局
*sql.DB后直接传给 handler——它本身线程安全,但事务/会话状态不跨协程 - 若用连接池(如
db.SetMaxOpenConns),确保context.WithTimeout传入 query,防止慢查询拖垮整个池
实际中最容易被忽略的点:参数化只保住了 WHERE 条件,但 ORDER BY、LIMIT、表名、字段名这些无法用 ? 占位的地方,必须走严格白名单校验。比如 ORDER BY ? 是语法错误,只能写成 ORDER BY "created_at" 并从预设列表里选。


















