MST

星途 面试题库

面试题:Go语言数据库操作中防止SQL注入的最佳实践探讨

阐述在Go语言中使用不同数据库(如MySQL、SQLite)时,防止SQL注入的通用方法和各自的特殊注意点。假设现有一个用户登录验证的SQL查询需求,用户输入用户名和密码,使用Go语言的database/sql包编写安全的查询代码示例。
26.5万 热度难度
编程语言Go

知识考点

AI 面试

面试题答案

一键面试

通用方法

  1. 使用参数化查询:在构建SQL语句时,使用占位符代替直接拼接用户输入的值。不同数据库的占位符形式可能不同,如MySQL使用?,SQLite也常用?database/sql包会自动处理参数值的转义和类型匹配,有效防止SQL注入。
  2. 输入验证和过滤:在接收用户输入后,对其进行验证,确保输入符合预期的格式和范围。例如,用户名通常只包含字母、数字等合法字符。虽然这不能完全替代参数化查询,但能进一步增强安全性。

MySQL特殊注意点

  1. 占位符使用:MySQL在database/sql包中使用?作为占位符。
  2. 驱动版本:确保使用的MySQL驱动版本是最新且稳定的,以获取最新的安全修复和特性。

SQLite特殊注意点

  1. 占位符使用:SQLite同样常用?作为占位符,但某些情况下也支持$name这种具名占位符形式。
  2. 事务处理:SQLite对事务支持较好,在进行复杂操作时,合理使用事务能保证数据的一致性和完整性。

代码示例

package main

import (
    "database/sql"
    "fmt"
    _ "github.com/go-sql-driver/mysql" // 假设使用MySQL,需导入对应驱动
)

func main() {
    // 数据库连接
    db, err := sql.Open("mysql", "user:password@tcp(127.0.0.1:3306)/yourdatabase")
    if err != nil {
        panic(err.Error())
    }
    defer db.Close()

    // 用户输入
    username := "testuser"
    password := "testpassword"

    var count int
    err = db.QueryRow("SELECT COUNT(*) FROM users WHERE username =? AND password =?", username, password).Scan(&count)
    if err != nil {
        fmt.Println("查询错误:", err)
        return
    }

    if count > 0 {
        fmt.Println("用户存在")
    } else {
        fmt.Println("用户不存在")
    }
}

若使用SQLite,导入SQLite驱动(如_ "github.com/mattn/go - sqlite3"),并修改连接字符串,如下:

package main

import (
    "database/sql"
    "fmt"
    _ "github.com/mattn/go - sqlite3"
)

func main() {
    db, err := sql.Open("sqlite3", "test.db")
    if err != nil {
        panic(err.Error())
    }
    defer db.Close()

    username := "testuser"
    password := "testpassword"

    var count int
    err = db.QueryRow("SELECT COUNT(*) FROM users WHERE username =? AND password =?", username, password).Scan(&count)
    if err != nil {
        fmt.Println("查询错误:", err)
        return
    }

    if count > 0 {
        fmt.Println("用户存在")
    } else {
        fmt.Println("用户不存在")
    }
}