# 安全
GORM 使用 `database/sql` 的參數占位符來構造 SQL 語句,這可以自動轉義參數,避免 SQL 注入數據
**注意** Logger 打印的 SQL 并不像最終執行的 SQL 那樣已經轉義,復制和運行這些 SQL 時應當注意。
## 查詢條件
用戶的輸入只能作為參數,例如:
```go
userInput := "jinzhu;drop table users;"
// 安全的,會被轉義
db.Where("name = ?", userInput).First(&user)
// SQL 注入
db.Where(fmt.Sprintf("name = %v", userInput)).First(&user)
```
## 內聯條件
```go
// 會被轉義
db.First(&user, "name = ?", userInput)
// SQL 注入
db..First(&user, fmt.Sprintf("name = %v", userInput))
```
## SQL 注入方法
為了支持某些功能,一些輸入不會被轉義,調用方法時要小心用戶輸入的參數。
```go
db.Select("name; drop table users;").First(&user)
db.Distinct("name; drop table users;").First(&user)
db.Model(&user).Pluck("name; drop table users;", &names)
db.Group("name; drop table users;").First(&user)
db.Group("name").Having("1 = 1;drop table users;").First(&user)
db.Raw("select name from users; drop table users;").First(&user)
db.Exec("select name from users; drop table users;")
```
避免 SQL 注入的一般原則是,不信任用戶提交的數據。您可以進行白名單驗證來測試用戶的輸入是否為已知安全的、已批準、已定義的輸入,并且在使用用戶的輸入時,僅將它們作為參數。