Espaces réservés ('?'
) ne peut être utilisé que pour insérer des valeurs dynamiques et échappées pour les paramètres de filtre (par exemple, dans WHERE
partie), où les valeurs de données doivent apparaître, pas pour les mots-clés SQL, les identifiants, etc. Vous ne pouvez pas l'utiliser pour spécifier dynamiquement le ORDER BY
OU GROUP BY
valeurs.
Vous pouvez toujours le faire, par exemple, vous pouvez utiliser fmt.Sprintf()
pour assembler le texte de la requête dynamique comme ceci :
ordCol := "title"
qtext := fmt.Sprintf("SELECT * FROM Apps ORDER BY %s DESC", ordCol)
rows, err := db.Query(qtext)
Éléments à garder à l'esprit :
Ce faisant, vous devrez vous défendre manuellement contre l'injection SQL, par ex. si la valeur du nom de la colonne provient de l'utilisateur, vous ne pouvez accepter aucune valeur et l'insérer directement dans la requête, sinon l'utilisateur pourra faire toutes sortes de mauvaises choses. Trivialement, vous ne devriez accepter que les lettres de l'alphabet anglais + chiffres + trait de soulignement ('_'
).
Sans essayer de fournir un vérificateur complet et complet ou une fonction d'échappement, vous pouvez utiliser cette simple expression rationnelle qui n'accepte que les lettres anglaises, les chiffres et '_'
:
valid := regexp.MustCompile("^[A-Za-z0-9_]+$")
if !valid.MatchString(ordCol) {
// invalid column name, do not proceed in order to prevent SQL injection
}
Exemples (essayez-le sur 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