Go语言防SQL注入的关键是禁用字符串拼接、强制参数化查询,对表名等标识符须白名单校验,ORM原生查询也需避免拼接。

Go 语言本身不会自动导致 SQL 注入,但用 fmt.Sprintf、strconv 拼接查询字符串,或直接把用户输入塞进 db.Query,就等于把门敞开。
用 database/sql 的参数化查询代替字符串拼接
Go 标准库的 database/sql 原生支持占位符(? 或 $1 等,取决于驱动),这是防注入最直接有效的手段。关键不是“用了预处理”,而是“没让用户输入参与 SQL 结构生成”。
常见错误写法:
// ❌ 危险:字符串拼接
username := r.URL.Query().Get("user")
rows, _ := db.Query("SELECT * FROM users WHERE name = '" + username + "'")正确做法:
立即学习“go语言免费学习笔记(深入)”;
// ✅ 安全:参数绑定
username := r.URL.Query().Get("user")
rows, _ := db.Query("SELECT * FROM users WHERE name = ?", username)- MySQL 驱动(
github.com/go-sql-driver/mysql)用? - PostgreSQL 驱动(
github.com/lib/pq)用$1,$2 - SQLite 驱动(
github.com/mattn/go-sqlite3)也支持?和命名参数(:name) - 不要试图自己转义引号或过滤单引号——绕过方式太多,且易漏
避免在查询中动态拼接表名、字段名或 ORDER BY 子句
参数化查询只适用于值(value),不适用于标识符(identifier):表名、列名、排序方向(ASC/DESC)无法用 ? 占位。这类场景必须白名单校验。
例如,允许前端指定排序字段:
// ❌ 错误:直接拼接
sortField := r.URL.Query().Get("sort")
rows, _ := db.Query("SELECT * FROM posts ORDER BY " + sortField + " DESC")应改为:
// ✅ 白名单控制
validSortFields := map[string]bool{"title": true, "created_at": true, "author_id": true}
sortField := r.URL.Query().Get("sort")
if !validSortFields[sortField] {
http.Error(w, "invalid sort field", http.StatusBadRequest)
return
}
rows, _ := db.Query("SELECT * FROM posts ORDER BY " + sortField + " DESC")- 永远不要信任用户输入来决定 SQL 结构部分
- 用
map[string]bool或switch列出所有合法值,拒绝其余一切 - ORDER BY 后的 ASC/DESC 同理,不能靠字符串替换或正则“过滤”
慎用 sql.Raw 和第三方 ORM 的原生查询接口
像 GORM 的 Raw()、Session().Exec(),或 sqlx 的 Queryx 带格式化字符串,都可能绕过参数化逻辑。只要里面出现 fmt.Sprintf 或 + 拼接,风险就回来了。
例如 GORM 中的典型误用:
// ❌ 危险:Raw 中拼接
name := r.FormValue("name")
db.Raw("SELECT * FROM users WHERE name = '" + name + "'").Scan(&users)应统一走参数化路径:
// ✅ 正确:Raw 支持问号占位
name := r.FormValue("name")
db.Raw("SELECT * FROM users WHERE name = ?", name).Scan(&users)- GORM v2+ 的
Where()方法默认安全(内部用参数绑定),优先用它 - 如果必须用
Raw,确保所有用户输入都作为参数传入,而非拼进 SQL 字符串 - 注意某些 ORM 的“命名参数”语法(如
:name)仍需配合sql.Named或对应驱动支持,不能混用
真正难防的不是技术点,而是开发时那一秒的“我就拼一下,反正这个字段前端可控”。SQL 注入漏洞往往藏在日志查询、导出接口、管理后台的模糊搜索里——这些地方最容易被当成“低风险”而跳过参数化。只要用户输入进了 SQL 字符串字面量,就该立刻停下来检查。










