Go 1.22 项目如何防止 SQL 注入:参数绑定、白名单与 GORM 风险点
时间:2026-08-23 | 作者:风起客 | 阅读:0必须用参数化查询防注入,占位符需匹配驱动规则(MySQL/SQLite用,PostgreSQL用$1);表名、字段名、ORDER BY等标识符须白名单校验,不可参数化。
必须用参数化查询,别拼字符串;驱动不认错占位符会直接报错;ORDER BY/表名/字段名不能参数化,得走白名单校验。
database/sql 的 Query/Exec 必须带正确占位符
Go 标准库 database/sql 本身不防注入,它只负责传参——真正起作用的是你写的 SQL 字符串干不干净。MySQL 和 SQLite 驱动只认 ,PostgreSQL 驱动只认 $1、$2。混用会立刻失败:
sql: expected 0 arguments, got 1:说明占位符没被识别,参数被当字面量丢进去了ERROR: syntax error at or near "123":常见于 PostgreSQL 里误写,驱动把它当普通字符解析了
实操建议:
- 查清你用的驱动(
github.com/go-sql-driver/mysql还是github.com/lib/pq),严格按其规则写占位符 - 永远用
db.Query("SELECT * FROM users WHERE id = AND status = ", id, "active"),而不是fmt.Sprintf("... id = %d", id) - 参数类型要匹配:传
int64给没问题,但传nil给非NULL字段会 panic,需用sql.NullInt64等显式类型
动态表名、字段名、ORDER BY 必须白名单校验
SQL标准是不允许对标识符(identifier)进行参数化的,因此所有驱动都会拒绝诸如ORDER BY 或SELECT FROM users这类语句,运行时会直接报错。有些人可能会将其改成fmt.Sprintf("ORDER BY %s", input),但这样做就相当于把数据库毫无保护地暴露出去了。
实操建议:
- 排序字段只允许从固定集合选:
validSortFields := map[string]bool{"created_at": true, "name": true, "score": true},查之前先判断validSortFields[input] - 表名映射用常量或 switch:
switch input { case "prod": tableName = "users_prod"; case "test": tableName = "users_test" },别拼"users_" + input LIMIT、OFFSET、GROUP BY同理,数值类参数可转int并做范围检查(如limit <= 100),字符串类必须白名单
GORM 等 ORM 也要小心 Raw() 和 Table() 的陷阱
GORM 默认开启 PrepareStmt,db.Where("name = ", name).Find(&u) 是安全的。但一旦调用 Raw() 或手动拼接表名,防护就失效了。
实操建议:
- 禁用
Raw():除非绝对必要,否则不用;真要用,也只拼白名单内的字段或表名,参数仍走或$1 - 用
Table(tableName)替代字符串拼接:db.Table(tableName).Where("id = ", id).Find(&u),前提是tableName来自配置或枚举,不是用户输入 - 检查 GORM 日志是否输出原始 SQL——如果看到
SELECT * FROM users WHERE name = 'admin'' OR ''1''=''1'这种,说明参数没绑上,得回溯代码找拼接点
Scan 接收 NULL 时类型必须显式声明
Scan 不参与防注入,但它出错会暴露结构、引发 panic,甚至间接导致逻辑异常。比如数据库字段允许 NULL,但你用 string 接收,遇到 NULL 就 panic;或者用 *string 却没判空,后续解引用崩掉。
实操建议:
- 字段可能为
NULL时,必须用sql.NullString、sql.NullInt64、sql.NullBool等类型接收 - 扫描后检查
.Valid字段:if name.Valid { fmt.Println(name.String) },别直接用name.String - 结构体字段加
sqltag 时注意:没有omitempty的NULL字段会覆盖已有值,容易引发静默数据污染
最易被忽略的点是:白名单校验和参数绑定是两套机制,缺一不可。占位符只保数据安全,保不住标识符;白名单只保标识符安全,保不住数据语义。两者必须同时落地,漏一个就等于开了后门。
免责声明:文中图文均来自网络,如有侵权请联系删除,心愿游戏发布此文仅为传递信息,不代表心愿游戏认同其观点或证实其描述。
相关文章
更多-
- 迅捷路由器怎么调信号最强,设置时要注意什么?
- 时间:2026-08-27
-
- vivo浏览器怎么卸不掉?原因和解决方法在这里
- 时间:2026-08-27
-
- OPPO R11s黑屏了,怎么强制恢复出厂设置?
- 时间:2026-08-27
-
- 飞利浦显示器包装盒有生产日期和保修期吗?怎么看?
- 时间:2026-08-27
-
- 联想新平板开机必须联网吗?怎么做?
- 时间:2026-08-27
-
- 平板横竖屏切换设置与问题解决
- 时间:2026-08-27
-
- 移动电源容量怎么测?要准备哪些工具?
- 时间:2026-08-27
-
- 荣耀90 Pro防水吗?防水级别多少?怎么用才安全
- 时间:2026-08-27
精选合集
更多大家都在玩
大家都在看
更多-
- 糖尿病完全不能吃糖吗
- 时间:2026-09-15
-
- 蚂蚁庄园小课堂2026年9月16日最新题目答案
- 时间:2026-09-15
-
- 小鸡答题今天的答案是什么2026年9月16日
- 时间:2026-09-15
-
- 蚂蚁庄园每日答题答案2026年9月16日
- 时间:2026-09-15
-
- 以下哪种粮食是酿造绍兴黄酒的主要原料 蚂蚁庄园今日答案9月16日
- 时间:2026-09-15
-
- 劝学名句“及时当勉励,岁月不待人”出自哪位诗人 蚂蚁庄园今日答案9.16
- 时间:2026-09-15
-
- 蚂蚁庄园今天答题答案2026年9月16日
- 时间:2026-09-15
-
- 蚂蚁庄园答题今日答案2026年9月16日
- 时间:2026-09-15
