2010-06-28 17 views
23

Mi chiedevo se fosse comunque necessario specificare i nomi di colonna restituiti utilizzando le istruzioni preparate.Nomi di colonne variabili utilizzando istruzioni preparate

Sto usando MySQL e Java.

quando provo è:

String columnNames="d,e,f"; //Actually from the user... 
String name = "some_table"; //From user... 
String query = "SELECT a,b,c,? FROM " + name + " WHERE d=?";//... 
stmt = conn.prepareStatement(query); 
stmt.setString(1, columnNames); 
stmt.setString(2, "x"); 

ricevo questo tipo di istruzione (diritto di stampa prima dell'esecuzione).

SELECT a,b,c,'d,e,f' FROM some_table WHERE d='x' 

Mi piacerebbe vedere però:

SELECT a,b,c,d,e,f FROM some_table WHERE d='x' 

So che non posso fare questo per i nomi di tabella, come discusso here, ma chiedevo se ci fosse un modo per farlo per la colonna nomi.

Se non c'è, allora dovrò solo assicurarmi di disinfettare l'input in modo che non porti a vulnerabilità di SQL injection.

risposta

24

Questo indica un design DB non valido. L'utente non dovrebbe aver bisogno di conoscere i nomi delle colonne. Crea una colonna DB reale che contiene quei "nomi di colonna" e memorizza invece i dati su di essa.

In qualsiasi modo, no, non è possibile impostare i nomi delle colonne come valori PreparedStatement. È possibile impostare solo colonna valori come PreparedStatement valori

Se vuoi continuare in questa direzione, è necessario disinfettare i nomi delle colonne e concatenare/costruire la stringa SQL da soli. Cita i nomi delle colonne separate e usa String#replace() per evitare la stessa citazione all'interno del nome della colonna.

+0

Bene, l'utente non ha effettivamente bisogno di conoscere i nomi delle colonne, ma i nomi delle colonne necessari sono dedotti in base ai moduli inviati dall'utente. Questo è gestito dal lato client, però, quindi volevo vedere se esisteva un modo per garantire la sicurezza dei dati. Dovrei quindi spostare l'intero lotto sul lato server, assicurando in tal modo che i dati della colonna non siano intaccati? – KLee1

+2

Gestirlo invece sul lato server. Non fare affari nel lato client. – BalusC

+0

@BalusC: _ "non puoi impostare i nomi delle colonne come valori PreparedStatement" _ - questo è completamente inventato. L'uso di nomi di colonne all'interno di liste di valori di istruzioni preparate è ovviamente possibile, ma ciò non significa che dovrebbe essere usato in questo modo, è ancora un cattivo progetto. – specializt

2

Penso che questo caso non possa funzionare perché l'intero punto dell'istruzione preparata è impedire all'utente di inserire bit di query senza escape, in modo che il testo venga citato o scappato.

È necessario disinfettare questo input in Java se si desidera influenzare in modo sicuro la struttura della query.

+0

Hai ragione sul "non può funzionare". Tuttavia, il primo motivo per PreparedStatement è stato a causa dell'efficienza delle risorse, che consente di mantenere un'istruzione memorizzata nella cache e di inviarla più volte semplicemente cambiando i valori (in particolare per OLTP). La sua resilienza ai tentativi di SQL Injection è un effetto collaterale molto utile. – Insac

12

Preparare una whitelist di nomi di colonne consentiti. Usa la 'query' per cercare nella whitelist per vedere se il nome della colonna è lì. In caso contrario, rifiuta la query.

0

Utilizzare lo svantaggio di SQL per l'interfaccia Statement come vantaggio. Es:

st=conn.createStatement(); 
String columnName="name"; 
rs=st.executeQuery("select "+ columnName+" from ad_org "); 
1

Di seguito è la soluzione in Java.

String strSelectString = String.format("select %s, %s from %s", strFieldName, strFieldName2, strTableName); 
+0

La tua risposta sembra ok, ma dovresti descrivere anche il tuo codice –

+5

Questa risposta porta direttamente a un attacco di SQL injection. –

0
public void MethodName(String strFieldName1, String strFieldName2, String strTableName) 
{ 
//Code to connect with database 
String strSQLQuery=String.format("select %s, %s from %s", strFieldName, strFieldName2, strTableName); 
st=conn.createStatement(); 
rs=st.executeQuery(strSQLQuery); 
//rest code 
} 
Problemi correlati