在使用 “database/sql” 时,我该如何在 Go 中防止 SQL 注入攻击?

huangapple go评论76阅读模式
英文:

How can I prevent SQL injection attacks in Go while using "database/sql"?

问题

构建我的第一个 Web 应用程序,并希望更好地理解 SQL 注入(https://github.com/astaxie/build-web-application-with-golang/blob/master/en/eBook/09.4.md)。

如果我始终使用 'database/sql' 库并使用 '?' 构建查询,而不是连接字符串,那么我能获得多少防止 SQL 注入的保护?在这种情况下,我仍然需要担心哪些类型的 SQL 注入攻击?

英文:

Building my first web-app and want to understand SQL injection better (https://github.com/astaxie/build-web-application-with-golang/blob/master/en/eBook/09.4.md).

How much protection against SQL injection do I get from just always using the 'database/sql' library and constructing queries using '?' instead of concatting strings? What kind of SQL injection attacks will I still have to worry about in that case?

答案1

得分: 46

只要你使用PrepareQuery,就是安全的。

// 这是安全的
db.Query("SELECT name FROM users WHERE age=?", req.FormValue("age"))
// 这样会导致 SQL 注入。
db.Query("SELECT name FROM users WHERE age=" + req.FormValue("age"))

英文:

As long as you're using Prepare or Query, you're safe.

// this is safe
db.Query("SELECT name FROM users WHERE age=?", req.FormValue("age"))
// this allows sql injection.
db.Query("SELECT name FROM users WHERE age=" + req.FormValue("age"))

答案2

得分: 7

我同意@Oneonone的答案。

如果你正在检索数据,可以这样做:

db.Query("SELECT name FROM users WHERE age=?", req.FormValue("age"))

如果你需要安全地插入大量数据,并且使用相同的查询,这就是Prepare派上用场的地方。你可以这样做:

tx, err := db.Begin()
if err != nil {
    return nil, err
}
stmt, err := tx.Prepare("INSERT INTO users VALUES (?, ?)")
if err != nil {
    tx.Rollback()
    return nil, err
}
defer stmt.Close()
for i := 0; i < 10; i++ {
    _, err = stmt.Exec(i, "dummy")
    if err != nil {
        tx.Rollback()
        return nil, err
    }
}
err = tx.Commit()
if err != nil {
    stmt.Close()
    tx.Rollback()
    return nil, err
}
stmt.Close()
return someValue, nil

参考:https://stackoverflow.com/a/46476451/5466534

英文:

I agree with @Oneonone's answer.

If you are retrieving data, do something like:

db.Query(&quot;SELECT name FROM users WHERE age=?&quot;, req.FormValue(&quot;age&quot;))

If you have to insert a lot of data safely, using the same query, this is where Prepare comes handy. you can do something like this:

tx, err := db.Begin()
if err != nil {
    return nil,err
}
stmt, err := tx.Prepare(&quot;INSERT INTO users VALUES (?, ?)&quot;)
if err != nil {
    tx.Rollback()
    return nil,err
}
defer 
for i := 0; i &lt; 10; i++ {
    _, err = stmt.Exec(i, &quot;dummy&quot;)
    if err != nil {
        tx.Rollback()
        return nil,err
    }
}
err = tx.Commit()
if err != nil {
    stmt.Close()
    tx.Rollback()
    return nil,err
}
stmt.Close()
return someValue, nil

ref: https://stackoverflow.com/a/46476451/5466534

答案3

得分: 0

如果准备好的语句不够用,你可以使用查询构建器。

我创建了 hotcoal 包,它可以帮助你保护手工编写的 SQL 免受注入攻击。它提供了一个简洁的 API,你可以与任何 SQL 库一起使用。

英文:

If prepared statements are not enough, you can use a query builder.

I created the hotcoal package, which helps you secure your handcrafted SQL against injection. It provides a minimal API and you can use it with any SQL library.

huangapple
  • 本文由 发表于 2014年10月14日 01:12:25
  • 转载请务必保留本文链接:https://go.coder-hub.com/26345318.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定