go - 使用 go-sql-driver 和 mysql 安全插入查询
问题描述
我已经使用 db.Prepare 查看了 go-sql-driver 示例,但我无法使其正常工作,因此我将其修改为直接使用 db.Query。我的理解是使用 ?? 无论如何,该值都被转义了,所以我想知道以下内容是否正确并且可以防止 SQL 注入(请注意,我使用的是 MySQL)
stmtIns, err := db.Query("INSERT INTO users (name, address) VALUES(?,?)", name, address) // ? = placeholder
if err != nil {
panic(err.Error()) // proper error handling instead of panic in your app
}
defer stmtIns.Close() // Close the statement when we leave main() / the program terminates
另外,检测是否已插入行的最佳方法是什么?
澄清:为了安全,我指的是 SQL 注入。我认为是这样,但后来我想知道为什么我能找到的所有示例都使用 db.Prepare 而不是 db.Query 。
解决方案
是的,这可以避免 SQL 注入攻击。
请注意,客户端代码不会在此类查询中“转义”参数。它做了一些更简单、更安全的事情:
客户端并没有将INSERT INTO users (name) VALUES(?)
参数组合;DROP TABLE USERS;
成INSERT INTO users (name) VALUES(;DROP TABLE USERS;
.
客户端也没有使用转义字符执行上述操作以使其“安全”。客户不构造类似的东西INSERT INTO users (name) VALUES("\;DROP TABLE USERS\;")
它所做的是向 MySQL 发送一个查询,其中分别包含:
- 查询字符串
INSERT INTO users (name) VALUES(?)
——MySQL 知道这是一个查询字符串,并且知道这?
是插入参数的位置。 - 参数
;DROP TABLE USERS;
-- MySQL 知道这是查询的参数
因此,服务器知道参数不是 SQL 代码,这巧妙地避免了转义字符的整个讨厌的问题。
通过选择不使用Prepare
,您正在跳过一些优化服务器的潜力。服务器将每个语句编译成内部表示,这需要时间。通过使这个显式并重新使用准备好的语句,您显式地节省了重复该编译步骤。
但是,MySQL 会缓存已编译的语句,以避免重复编译完全相同的字符串——因此您可能不会看到大的性能问题。
推荐阅读
- python - 响应 400
在 Dreamfactory API POST 调用上 - php - 使用 Sessions 在 Web 应用程序中处理长时间且耗时的 ajax 调用
- java - 在 Native SQL Hibernate 中使用 addJoin 的列中出现异常
- javascript - Javascript:单击图像时播放音频
- javascript - Express JS 用接收到的图像渲染视图
- python - 我正在使用乳齿象 python api,我正在尝试从输出字典中访问用户名。但它无法访问
- wildcard - 通配符和自动子域
- c - C 中数组和指针的基本行为
- ubuntu-16.04 - 控制台调试器路由器我连接被拒绝
- postgresql - 数据库的总大小大于 Postgresql 中每个表大小的总和