Tijdelijke aanduidingen ('?'
) kan alleen worden gebruikt om dynamische, escaped-waarden voor filterparameters in te voegen (bijv. in de WHERE
deel), waar gegevenswaarden moeten verschijnen, niet voor SQL-sleutelwoorden, identifiers enz. U kunt het niet gebruiken om dynamisch de ORDER BY
op te geven OF GROEPEREN OP
waarden.
U kunt het echter nog steeds doen, u kunt bijvoorbeeld fmt.Sprintf()
om de dynamische vraagtekst als volgt samen te stellen:
ordCol := "title"
qtext := fmt.Sprintf("SELECT * FROM Apps ORDER BY %s DESC", ordCol)
rows, err := db.Query(qtext)
Dingen om in gedachten te houden:
Als u dit doet, moet u handmatig verdedigen versus SQL-injectie, b.v. als de waarde van de kolomnaam van de gebruiker komt, kun je geen enkele waarde accepteren en deze gewoon rechtstreeks in de query invoegen, anders kan de gebruiker allerlei slechte dingen doen. Triviaal zou je alleen letters van het Engelse alfabet + cijfers + underscore moeten accepteren ('_'
).
Zonder te proberen een complete, allesomvattende checker- of escape-functie te bieden, kunt u deze eenvoudige regexp gebruiken die alleen Engelse letters, cijfers en '_'
accepteert. :
valid := regexp.MustCompile("^[A-Za-z0-9_]+$")
if !valid.MatchString(ordCol) {
// invalid column name, do not proceed in order to prevent SQL injection
}
Voorbeelden (probeer het op de Go Playground ):
fmt.Println(valid.MatchString("title")) // true
fmt.Println(valid.MatchString("another_col_2")) // true
fmt.Println(valid.MatchString("it's a trap!")) // false
fmt.Println(valid.MatchString("(trap)")) // false
fmt.Println(valid.MatchString("also*trap")) // false