17 filtrare i dati con PDO
Il metodo presentato precedentemente, oltre che altamente scomodo, risulta essere anche particolarmente insicuro, infatti è passibile di SQL injection, pensate aggiungere
http://127.0.0.1:8000/albums?id=2&album_name="pippo" or 1=1
In questo caso un utente potrebbe passarci un parametro del genere via GET e avrebbe accesso a tutti i dati, pensate solo ad un login, mostreremmo tutte le credenziali perchè la query 1=1 risulta TRUE.
Riformuliamo il codice utilizzando i PDO
Metodo coi segnaposti
Intanto inizializziamo la $where come array vuoto, poi lasciamo la condizione $request->has(‘id’) e il suo valore lo inseriamo nell’array $where inserendo anche la chiave id
public function index(Request $request) { $sql = 'select * from albums'; $where = []; if($request->has('id')) { $where['id'] = $request->get('id'); }
Stessa cosa facciamo se c’è anche album_name
if($request->has('album_name')) { $where['album_name'] = $request->get('album_name'); }
ora modifichiamo $sql aggiungendo WHERE 1=1
$sql = 'select * from albums WHERE 1=1';
adesso molto semplicemente nell’if dell’id concateniamo un AND id=? dove il punto di domanda è il nostro segna posto
$sql .= ' AND id=?';
stessa cos per album_name
if($request->has('album_name')) { $where['album_name'] = $request->get('album_name'); $sql .= ' AND album_name=?'; }
Adesso al metodo select() della nostra facade DB passiamo anche i valori dell’array $where.
Per passare solo i valori di un array senza le chiavi usiamo il metodo php array_values()
return DB::select($sql, array_values($where));
Passando i parametri in questo modo, la SQL injection non funzionerà, perchè i valori vengono passati tramite l’array $where che li prende dai segna posti e non inseriti nel comando SQL in una variabile
Metodo per riferimento
è molto simile al precedente, solo che invece che usare il punto di domanda si usano i due punti seduiti dal nome della chiave che riceve il dato
$sql .= ' AND id=:id'; $sql .= ' AND album_name=:album_name';
a questo punto a DB::select() passiamo anche le chiavi, quindi rimuoviamo la funzione array_values().
public function index(Request $request) { $sql = 'select * from albums WHERE 1=1'; $where = []; if($request->has('id')) { $where['id'] = $request->get('id'); $sql .= " AND id=:id"; } if($request->has('album_name')) { $where['album_name'] = $request->get('album_name'); $sql .= " AND album_name=:album_name"; } //dd($sql); return DB::select($sql, $where); }
Come abbiamo visto questi metodi con i PDO oltre che più sicuri sono anche più semplici da costruire.