Il prefisso sql
sblocca un StringContext
in cui è possibile impostare i parametri SQL. Non esiste un parametro SQL per un elenco, quindi puoi facilmente finire per aprirti all'iniezione SQL qui se non stai attento. Ci sono alcuni buoni (e alcuni pericolosi) suggerimenti su come gestire questo problema con SQLServer su this question. Hai un paio di opzioni:
La cosa migliore è probabilmente quello di utilizzare l'operatore #$
insieme mkString
interpolare SQL dinamico:
val sql = sql"""SELECT * FROM coffee WHERE id IN (#${ids.mkString(",")})"""
Questo non usa correttamente i parametri e quindi potrebbe essere aperto a sql- iniezione e altri problemi.
Un'altra opzione è quella di utilizzare regolare l'interpolazione di stringa e mkString
per creare l'istruzione:
val query = s"""SELECT * FROM coffee WHERE id IN (${ids.mkString(",")})"""
StaticQuery.queryNA[Coffee](query)
Questo è essenzialmente lo stesso approccio utilizzando #$
, ma potrebbe essere più flessibili nel caso generale.
Se la vulnerabilità di SQL-injection è una delle principali preoccupazioni (ad esempio se gli elementi di ids
sono forniti dall'utente), è possibile creare una query con un parametro per ciascun elemento di ids
. Allora è necessario fornire un campione personalizzato SetParameter
in modo che chiazza di petrolio può trasformare il List
in parametri:
implicit val setStringListParameter = new SetParameter[List[String]]{
def apply(v1: List[String], v2: PositionedParameters): Unit = {
v1.foreach(v2.setString)
}
}
val idsInClause = List.fill(ids.length)("?").mkString("(", ",", ")")
val query = s"""SELECT * FROM coffee WHERE id IN ($idsInClause)"""
Q.query[List[String], String](query).apply(ids).list(s)
Dal momento che il ids
sono Ints
, questo è probabilmente meno di una preoccupazione, ma se si preferisce questo metodo, avrebbe solo bisogno di cambiare il setStringListParameter
di utilizzare Int
invece di String
:
Se 'ids' ha tipo' List [Int] 'Non riesco a vedere come sql injection è possibile anche se sono forniti dall'utente. – Daenyth
@Daenyth E 'sicuramente meno preoccupante (anche se a volte l'integer SQL può essere un problema, causando una divisione per zero o altre eccezioni, e quindi sfruttando lo stato fallito - Google "sql injection interi"). Ma direi che è meglio usare i parametri per evitare problemi lungo la strada (ad esempio, se un altro sviluppatore modificasse il tipo in 'String' down per adattare i nuovi tipi di ID che includono alcuni caratteri). Stavo davvero coprendo il caso quando qui c'è un 'String'. –
Grazie per la risposta Ben! Molto informativo delle soluzioni con possibili vulnerabilità. Sono comunque d'accordo con @Daenyth che non si può iniettare sql con un tipo intero esplicito. –