Domanda

Sto cercando di essere un buon CF sviluppatore web e utilizzare <cfqueryparam> attorno a tutti gli elementi forma o URL che lo rendono ai miei query SQL.

In questo caso, sto cercando di consentire a un utente di controllare la clausola ORDER BY in modo dinamico.

<cfquery datasource="MyDSN" name="qIncidents">
  SELECT IncidentID, AnimalID, IntakeDate, DxDate, OutcomeDate
  FROM Incidents
  WHERE ShelterID = <cfqueryparam cfsqltype="cf_sql_integer" value="#Arguments.ShelterID#">
  ORDER BY <cfqueryparam cfsqltype="cf_sql_varchar" value="#SortBy#">
</cfquery>

Quando faccio questo, ottengo il seguente errore:

  

Il SELECT identificato da ORDER BY numero 1 contiene una variabile come parte dell'espressione identificare una posizione di colonna. Variabili sono consentiti solo al momento dell'ordine da un'espressione riferimento a un nome di colonna.

Qualche suggerimento su come farlo in modo sicuro?

È stato utile?

Soluzione

Purtroppo, non è possibile utilizzare CFQUERYPARAM direttamente nella clausola ORDER BY.

Se si desidera utilizzare ORDER BY in modo dinamico ma ancora farlo in modo sicuro, è possibile impostare un CFSWITCH o struttura simile per cambiare la variabile SortBy base a una certa condizione (per esempio, una variabile URL). Come sempre, non passano alcun valore direttamente dall'utente, basta guardare l'input dell'utente e selezionare da un elenco predeterminato di valori possibili in base a questo. Poi, basta usare la sintassi standard:

ORDER BY #SortBy#

Altri suggerimenti

mi limiterò a spieghi la risposta di Aaron. Una delle cose che faccio è quello di utilizzare listfindnocase () per fare in modo che gli argomenti passati per la clausola ORDER BY sono validi:

<cfset variables.safeSortColumn = "name">
<cfset variables.safeSortOrder = "desc">

<cfparam name="url.sortcolumn" type="string" default="#variables.safeSortColumn#">
<cfparam name="url.sortorder" type="string" default="#variables.safeSortOrder#">

<cfif listfindnocase("name,age,address", url.sortcolumn)>
    <cfset variables.safeSortColumn = url.sortcolumn>
</cfif>

<cfif listfindnocase("desc,asc", url.sortorder)>
    <cfset variables.safeSortOrder = url.sortorder>
</cfif>

<cfquery>
select *
from mytable
order by #variables.safeSortcolumn# #variables.safeSortorder#
</cfquery>

il problema con l'utilizzo del valore ordinale di un riferimento di colonna è che è (credo) il valore ordinale al momento della dichiarazione di creare SQL tavolo è stato eseguito - in modo da aggiungere colonne alla tabella di database nel corso del tempo, lo strumento GUI si utilizza per visualizzare le colonne non può rappresentare il suo valore ordinale reale. Vorrei davvero stare lontano da utilizzando cfqueryparam per questo.

Mi piace l'idea di utilizzare un numero nelle variabili di richiesta (url, form) per specificare quali colonna per ordinare e quindi utilizzare tale nello switch e tradurlo in un nome di colonna effettivo - in modo da non esporre la colonna nomi per l'utente.

per quanto quando / perché usare cfqueryparam, tenere a mente la sua non solo sulla convalida di ingresso e SQL injection prevenzione (anche se questo è un bel bonus) - con cfqueryparam SQL sottostante al database viene inviato indietro attraverso il driver utilizzando SQL variabili di bind - valori segnaposto, quindi l'ottimizzatore databse in grado di determinare quale indice utilizzare in un formato più generico ... così quando si invia un'istruzione SQL come questo: SELECT * FROM prodotto WHERE ID = 1 e SELECT * FROM WHERE prodotto ID = 2 l'ottimizzatore esegue entrambe le volte. ma con variabili di bind, la SQL assomiglia a questo SELECT * FROM prodotto WHERE ID =? (? = 1) e SELECT * FROM prodotto WHERE ID =? (? = 2) in modo da l'ottimizzatore può utilizzato i risultati memorizzati nella cache della prima analisi di sapere esattamente cosa indice da utilizzare sulla seconda query. a seconda della complessità del SQL e il database questo può essere un enorme risparmio di tempo. nella mia esperienza la sua molto utile prestazioni saggio con Oracle e data / ora colonne nella clausola WHERE.

in modo, per quanto dove utilizzare cfqueryparam, il suo dove può essere utilizzata una variabile SQL bind ...

hth jon

Per quanto riguarda il commento sull'uso "cfqueryparam nella bella clausola di ordine con MySQL". Sì, credo che è consentito con origini dati di MySQL. Anche se utilizzando la colonna ordinale , non il nome della colonna (che sembra essere trattato come un una stringa costante, invece).

Purtroppo, non sembra funzionare affatto per origini dati MS SQL. Almeno non da quello che posso dire.

<!--- this works --->
<cfset url.sortColumnNumber = "3">
<cfquery name="getDataByPosition" datasource="MySQLDSN">
   SELECT  RecordID, ProductName, DateAdded
   FROM TestTable
   ORDER BY <cfqueryparam value="#url.sortColumnNumber#" cfsqltype="cf_sql_integer"> ASC
</cfquery>
<cfdump var="#getDataByPosition#">

<!--- this does NOT work --->
<cfset url.sortColumnName = "DateAdded">
<cfquery name="getDataByName" datasource="MySQLDSN">
   SELECT  RecordID, ProductName, DateAdded
   FROM    TestTable
   ORDER BY <cfqueryparam value="DateAdded" cfsqltype="cf_sql_varchar"> ASC
</cfquery>
<cfdump var="#getDataByName#">

Aggiornamento: Per quanto riguarda i commenti su ordinale: No, credo che si riferisce alla posizione della colonna nell'elenco di selezione, non la tabella sottostante. Così dovrebbe andare bene.

Si, accetto la protezione SQL injection non è lo scopo principale della cfqueryparam. Così la descrizione di variabili di bind è stata una buona aggiunta.

Ho pensato di buttare codice minore a questo problema:

<cfset sortColumns = {IncidentID = "IncidentID", AnimalID = "AnimalID", IntakeDate = "IntakeDate", DxDate = "DxDate", OutcomeDate = "OutcomeDate"}>
<cfset sortDirections = {ASC = "ASC", DESC = "DESC"}>

<cfquery datasource="MyDSN" name="qIncidents">
    SELECT IncidentID, AnimalID, IntakeDate, DxDate, OutcomeDate
    FROM Incidents
    WHERE ShelterID = <cfqueryparam cfsqltype="cf_sql_integer" value="#Arguments.ShelterID#">
    ORDER BY #sortColumns[sortBy]# #sortDirections[sortDirection]#
</cfquery>

Dove sortby e sortDirection entrano tramite l'URL o dove mai.

Mi piace questo perché è pulito e non si può iniettare qualsiasi cosa tramite la clausola ORDER BY.

Qualche commento?

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top