避免SQL注入風險

您可以透過將SQL引數值作為sql包函式引數提供來避免SQL注入風險。sql包中的許多函式都為SQL語句及其引數中使用的值提供了引數(其他函式則為預處理語句和引數提供引數)。

以下示例中的程式碼使用?符號作為id引數的佔位符,該引數作為函式引數提供。

// Correct format for executing an SQL statement with parameters.
rows, err := db.Query("SELECT * FROM user WHERE id = ?", id)

執行資料庫操作的sql包函式會根據您提供的引數建立預處理語句。在執行時,sql包會將SQL語句轉換為預處理語句,並將其與單獨的引數一起傳送。

注意:引數佔位符因您使用的DBMS和驅動程式而異。例如,Postgres的pq驅動程式接受$1形式的佔位符,而不是?

您可能會想使用fmt包中的函式來將SQL語句組裝成一個包含引數的字串——像這樣:

// SECURITY RISK!
rows, err := db.Query(fmt.Sprintf("SELECT * FROM user WHERE id = %s", id))

這不安全!當您這樣做時,Go會在將完整的語句傳送到DBMS之前,組裝整個SQL語句,用引數值替換%s格式動詞。這會帶來SQL注入風險,因為程式碼的呼叫者可能會將意外的SQL片段作為id引數傳送。該片段可能會以對您的應用程式危險的不可預測的方式完成SQL語句。

例如,透過傳遞特定的%s值,您最終可能會得到類似以下的內容,這可能會返回資料庫中的所有使用者記錄:

SELECT * FROM user WHERE id = 1 OR 1=1;