Cosa sono i filtri? [tutorial php]

Per autenticare un valore passato ad uno script php si usano, ad esempio,  htmlspecialchars e htmlentities.

Essi trasformano i valori riportati qui sotto (htmlentities in realtà ne trasforma anche altre.)

  •    '&' (e commerciale) diventa '&'
  • '"' (doppio apice) diventa '"' con ENT_NOQUOTES non settata.
  • ''' (singolo apice) diventa ''' soltanto con l'impostazione di ENT_QUOTES.
  • '<' (minore) diventa '&lt;'
  • '>' (maggiore) diventa '&gt;'

In particolare i caratteri dichiarati speciali vengono trasformati nelle loro entità, con questo metodo si assicura il fatto che una stringa che inizi con <script> ad esempio passato tramite un form, non abbia effetto alcuno.

Nella pratica questo è un paliativo dato che si può aggirare il problema, ma non solo, ad esempio si possono passare le query in SQL che non abbiano caratteri speciali al loro interno.

Ovviamente tutto ciò ha effetto se poi il valore passato viene dato in pasto ad SQL o a istruzioni del php che usano la stringa per lanciare altre applicazioni; insomma non è una buona pratica usare questi metodi per applicazioni complesse.

Per questi motivi dalla versione 5.2.0 del php (e in quelle prima ma sempre della versione 5 nel PECL)  l'autenticazione dei valori passati tra una sessone e l'altra può essere realizzata da alcune funzioni costruite apposta: i filtri!

Per utilizzarli oltre ad avere sul server una delle ultime versioni del linguaggio php bisogna conoscerne la sintassi.

Essa è tutto sommato semplice, ma molto flessibile, in poche parole la stringa da valutare viene passata ad una delle sette funzioni di cui si compongono i filtri:

  • filter_has_var - controlla che una specifica variabile sia vera, cioè ritorni un valore, ad esempio: filter_has_var(INPUT_POST, 'submit'), altrimenti si usa isset($_POST['submit']).
  • filter_id - ritorna l'IDentificativo della variabile passata al filtro.
  • filter_input_array - controlla un numero qualsiasi di variabili passate come una matrice, è il filtro sicuramente più importante per la sua versatilità, ritona una matrice contente i valori delle variabili controllate in input, il suo campo di applicazione è vasto e va visto a parte.
  • filter_input - è simile al filtro precedente, ma controlla una variabile alla volta, anche questo ha un campo di appliczione vasto e va visto a parte.
  • filter_list - ritorna una lista dei filtri supportati dalla versine del php in uso, con questo potrete verificare che la versione del php che state usando supporti i filtri, se il suo valore è negativo ad esempio, potete implementare un metodo alternativo che usi altri metodi di validazione, così da rendere la vostra applicazione portabile su altre e meno recenti versioni del php. Attenzione ritorna una matrice (array) che se vuoto può essere assimilato a false
  • filter_var_array - simile a filter_input_array offre un buon sistema per controllare una matrice di valori e confrontarla, opzionalmente, con una matrice di controlli.
  • filter_var - simile al precedente ma controlla una variabile alla volta.

Se avete dato un'occhiata alla pagina dei filtri sul manuale, vi sarete accorti che ci sono una miriade di costanti predefinite che vengono usate per la validazione degli input, alcune sono persino l'accoppiamento di altre costanti, in grado quindi, di validare valori in modo molto preciso.

Realizzare una guida per controllare una serie di variabili è un'impresa ardua dato il vastissimo campo di utilizzo, però qualcun altro ci ha pensato e ha realizzato alcuni articolo esplicativi (in inglese), ad esempio su

sono molto semlici da seguire, provatele e vedrete che non potrete più fare a maeno dei filtri.

Un piccolo esempio: a volte si passa via url una variabile numerica che poi viene processata magari attraverso un ciclo o tramite uno switch per reindirizzare l'utente verso altre pagine del sito.

Mettiamo il caso un menù in cui tutti gli uri sono passati tramite un valore numerico (pessima pratica per i motori di ricerca, ma si fa)

<ul>
<li><a href='/./?id=0'>home page</a></li>
<li><a href='/./?id=2'>foto</a></li>
<li><a href='/./?id=3'>contatti</a></li>
</ul>

e poi attraverso il php

if (isset($_GET['id'])) {
    $riferimento = (int)$_GET['id'];
    switch($riferimento) {
       case 0: manda all'url corrispondente
       case 1: manda all'url corrispondente
       case 2: manda all'url corrispondente
       default: manda in home page se manca un riferimento nell'url
    }
}

tutto ciò funziona ma non si può essere sicuri di ciò che viene passato tramite la variabile id dell'url, (int) non ci mette al riparo da entità o da valori arbitrari, ad esempio se viene passato il carattere a come ID, (int) lo trasforma nel suo valore ASCII che se non ricordo male vale 122, insomma è pur sempre un valore arbitrario che nell'esempio di cui sopra rimanderebbe l'utente all'home page del sito (default nell'espressione switch), ciò sembrerebbe comunque funzionare per il meglio, ma non bisogna mai lasciare nulla al caso, non bisognerebbe mai far si che l'utente passi valori talmente grandi che possano persino mandare la macchina in blocco.

E allora? Allora che i filtri siano  ;D

sostituiamo questo pezzo di codice

if (isset($_GET['id'])) {
    $riferimento = (int)$_GET['id'];

con

if (filter_has_var(INPUT_GET, 'id')) {
    $riferimento = filter_var($_GET['id'], FILTER_VALIDATE_INT, array("min_range"=>0, "max_range"=>3));

ed ecco che oltre a validare con sicurezza che il valore passato si un intero, esso viene controllato persino per ricadere dentro un range minimo e massimo, ora l'espressione accetta solo valori interi compresi tra 0 e 3, meglio di così si muore :)

Tenete presente che le chiavi "min_range" e "max_range" non hanno nomi arbitrari, ma devo essere richiamate così o non funzionerebbe.

M.

inviato 8 anni fa
Marco Grazia
X 0 X

C'è un piccolo errore di sbaglio nell'espressione di cui sopra

if (filter_has_var(INPUT_GET, 'id')) {
    $riferimento = filter_var($_GET['id'], FILTER_VALIDATE_INT, array("min_range"=>0, "max_range"=>3));

in realtà ho dimenticato una matrice  ::) capita.

if (filter_has_var(INPUT_GET, 'id')) {
    $riferimento = filter_var($_GET['id'], FILTER_VALIDATE_INT, array("options" => array("min_range"=>0, "max_range"=>3));

questa è la versione corretta.

risposto 8 anni fa
Marco Grazia
X 0 X

Piccola aggiunta: dato che stiamo validando una stringa (o intero che sia) passata tramite url, possiamo anche usare i filtri già costruiti per lo scopo, per esempio il codice di prima diventerebbe:

if (filter_has_var(INPUT_GET, 'id')) {
    $riferimento = filter_input(INPUT_GET, 'id', FILTER_VALIDATE_INT, array("options" => array("min_range"=>0, "max_range"=>3));

in pratica in luogo di filter_var ho usato filter_input i due filtri sono simili ma il secondo permette un controllo immediato sull'url di riferimento.

In questo caso ho usato la costante chiamata INPUT_GET dato che era appunto una variabile passata tramite questo metodo, se invece la variabile veniva passata tramite il metodo post, avrei utilizzato la costante INPUT_POST.

A seguire realizzerò una piccola applicazione per spedire un'email che utilizza i filtri per controllare ciò che l'utente tenta di inviare tramite il form di spedizione.

risposto 8 anni fa
Marco Grazia
X 0 X
Effettua l'accesso o registrati per rispondere a questa domanda