Nessun risultato. Prova con un altro termine.
Guide
Notizie
Software
Tutorial

La libreria Filter: filtrare l'input degli utenti con PHP 5.2

Introduzione all'uso della libreria Filter, introdotta in PHP 5.2 per filtrare l'input degli utenti con efficacia e mediante l'uso di poche istruzioni.
Introduzione all'uso della libreria Filter, introdotta in PHP 5.2 per filtrare l'input degli utenti con efficacia e mediante l'uso di poche istruzioni.
Link copiato negli appunti

Sul blog di HTML.it e da molte altre fonti si è ormai appreso (e compreso) che uno degli argomenti caldi del momento legati al mondo di PHP è quello della sicurezza. Ormai i linguaggi per lo sviluppo web hanno raggiunto piena maturità e sono pronti per gettarsi definitivamente nell'ambito dello sviluppo enterprise; in situazioni come queste la sicurezza del software rappresenta una condizione necessaria per assicurare un lavoro stabile e completo.

PHP ha ancora un po' di strada da percorrere nel senso della sicurezza, ma grazie al progetto Hardened PHP ed alla sua futura inclusione in PHP 6 possiamo dormire sonni tranquilli. Uno dei punti fondamentali per assicurarsi che il proprio software sia sicuro è proteggerlo da colore che, in buona o mala fede, inviano ai nostri script dati corrotti in varia forma.

Le estensioni per il filtraggio dei dati in input, introdotti come libreria opzionale ed ora integrati nella release ufficiale a partire da PHP 5.2, sono un ottimo sistema per prevenire attacchi di questo tipo, validare l'input ed assicurarsi che tutto quello su cui operiamo sia stato correttamente accettato dal nostro script.

Nell'articolo di oggi parleremo per l'appunto di come filtrare l'input ed i dati che poi manipoleremo con le nostre funzioni PHP attraverso le funzionalità fornite da PHP 5.2, quindi lavoreremo sul concetto di non prendere mai per sicuri i dati provenienti dall'esterno ma non tutti quegli argomenti derivati come attacchi XSS o SQL Injections.

Filtrare i dati

Filtrare i dati in input (si veda a proposito la nostra guida alla sicurezza di PHP) è uno dei punti iniziali (insieme ad un corretto design che prenda in considerazione la sicurezza fin dalle prime righe di codice) per rendere le proprie applicazioni sicure; è un'operazione semplice da archiviare manualmente, ma le estensioni fornite con PHP fanno ancora di più, fornendoci una buona dose di opzioni aggiuntive con le quali lavorare anche in situazioni complesse.

I dati in input che dovrebbero essere filtrati e validati sono solitamente tutti quelli che provengono dai form (sia via GET sia via POST), il contenuto dei cookie (che comunque dovrebbe essere sempre criptato in modo da assicurarci la validità delle informazioni in esso contenute), i dati provenienti da Web service esterni od interni al nostro dominio ed alcune variabili contenute nell'array globale $_SERVER. In alcuni casi risulta comunque importante assicurarsi che anche i risultati delle query, le variabili d'ambiente ed il contenuto di alcuni file non siano stati corrotti oppure abbiano dati validi e comprensibili per il nostro sistema.

Quando si sviluppa in PHP e si desidera fare un controllo (semplice e procedurale) sull'input, si opera solitamente con codice condizionale che controlla il valore dei dati in input utilizzando semplici espressioni (l'esempio è puramente indicativo e sarebbe meglio evitare codice simile in ambiente di produzione):

<?php

$name = "";
$age = 0;
$error = null;

if(isset($_GET['name']))
{
   $name = $_GET['name'];
   if(strlen(trim($name)) < 3)
   {
      $error = "Il nome e' troppo corto";
   }else
   {
      if(isset($_GET['age']))
      {
         $age = $_GET['age'];
         if(!is_numeric($age))
         {
            $error = "L'età specificata deve essere un numero";
         }else
         {
            if($age < 0 || $age > 80)
            {
               $error = "L'età specificata non è corretta";
            }
         }
      }
   }
}else
{
   $error = "Il nome deve essere specificato";
}

if(!is_null($error))
{
   echo $error;
}else
{
   echo $name." ".$age;
}

?>

Grazie alla libreria per filtrare l'input invece possiamo sfruttare dei validatori e delle funzioni implementate di default e semplificarci il lavoro:

<?php

$name =   filter_input(INPUT_GET, 'name',   FILTER_VALIDATE_REGEXP, array(
         'options' => array(
            'regexp' => "/[a-z]{3,}/i")));

$age =   filter_input(INPUT_GET, 'age',   FILTER_VALIDATE_INT, array(
         'options' => array(
            'min_range' => 0,
            'max_range' => 80)));

switch(true)
{
   case is_null($name):
      echo "Il nome non è stato specificato";
   break;
   
   case is_null($age):
      echo "L'età non è stata specificata";
   break;
   
   case $name == false:
      echo "Il nome non è stato specificato nel formato corretto";
   break;
   
   case $age == false:
      echo "L'età deve essere un numero compreso tra 0 e 80";
   break;
   
   default:
      echo $name." ".$age;
   break;
   
}

?>

Come possiamo notare il codice è molto pulito e lineare ed è possibile sfruttare alcuni validatori interni forniti dalla libreria per poter lavorare senza praticamente aggiungere codice manualmente alla libreria. Ovviamente è sempre buona norma rivestire con un interfaccia la libreria Filter al fine di rendere la validazione ed il controllo dei dati in input un'operazione ben integrata con il nostro codice ed i nostri script.

La libreria Filter espone due tipologie di filtri, che andremo ad analizzare in dettaglio successivamente; il primo tipo di filtri sono quelli che si occupano di ripulire i dati permettendo di limitare i caratteri presenti all'interno di una stringa (come tag potenzialmente nocivi o codifiche non accettate), sono preceduti da FILTER_SANITIZE_* e restituiscono sempre una stringa in output; il secondo tipo invece sono i filtri logici che effettuano un'analisi approfondita dei dati validando i formati e restituendo il tipo di dato aspettato nel caso le operazioni avvengano con successo.

La libreria Filter in dettaglio

Vediamo ora brevemente quali sono le funzionalità esposte dalla libreria e quali sono i filtri che possiamo utilizzare per facilitarci la vita e rendere più sicure le nostre applicazioni.

La libreria Filter espone le seguenti funzioni:

  • filter_has_var( int type, string name): controlla che una variabile del tipo specificato esista;
  • filter_id(string name): restituisce un intero che rappresenta il filtro specificato per nome come primo parametro;
  • filter_input_array(int type, array $def): filtra una serie di variabili in input in base alle opzioni specificate nell'array passato come secondo parametro;
  • filter_input(int type, string name, int flags, array options): filtra una variabile in input in base alle opzioni specificate;
  • filter_var(mixed var, int flags, array options): filtra una variabile con il filtro specificato;

Le funzioni filter_input* e filter_var* restituiscono false nel caso in cui l'input non sia stato filtrato correttamente, null nel caso in cui la variabile non sia impostata ed un valore basato sul tipo di filtro richiesto nel caso in cui tutto vada per il verso giusto.

I filtri applicabili sono a loro volta molteplici, ed accettano un numero differente di opzioni e flag per il controllo del comportamento. Per una lista esaustiva rimando alla documentazione ufficiale sul sito PHP.net.

Vediamo ora qualche esempio pratico di come sfruttare i filtri forniti con la libreria Filter; creeremo un form che ci occuperemo di validare dopo il suo invio. Al fine di rendere il codice il più comprensibile e ordinato possibile utilizzeremo la funzione filter_input_array che ci permette di specificare le opzioni di validazione all'interno di un array e filtrare tutti i dati con una sola chiamata.

Il form è una semplice maschera per la raccolta di dati:

<html>
   <head>
      <title>PHP 5.2 - Filter Library</title>
   </head>
   <body
      <form action="submit.php" method="POST">
         <label>Nome: </label>
         <input name="name">
         <br />

         <label>Username: </label>
         <input name="username">
         <br />
         
         <label>Email: </label>
         <input name="email">
         <br />
         
         <label>Età: </label>
         <input name="age">
         <br />
         
         <label>Nazionalità: </label>
         <select name="nationalities[]">
            <option value="Italiana"> Italiana </option>
            <option value="Inglese"> Inglese </option>
            <option value="Francese"> Francese </option>
         </select>
         <br />
         
         <label>Note: </label>
         <textarea name="notes"></textarea>
         <br />

         <input type="submit" name="submit" value="Invia" />
      </form>
   </body>
</html>

Il file submit.php invece utilizza la libreria Filter per validare e filtrare i dati:

<?php

function check_username($username)
{
   // Sarebbe opportuno un controllo più utile
   return (strlen($username) > 8);
}

if (!filter_has_var(INPUT_POST, 'submit'))
{
   header('Location: form.html');
   exit();
}

$definitions = array(
   'name' => array(
      'filter' => FILTER_SANITIZE_STRING,
      'flags'  => FILTER_FLAG_ENCODE_HIGH | FILTER_FLAG_ENCODE_LOW),
   
   'username' => array(
      'filter' => FILTER_CALLBACK,
      'options' => 'check_username'),

   'email' => FILTER_VALIDATE_EMAIL,

   'age' => array(
      'filter' => FILTER_VALIDATE_INT,
      'options'=> array('min_range' => 0, 'min_range' => 80)),

   'nationalities' => array(
      'filter' => FILTER_SANITIZE_STRING,
      'flags' => FILTER_REQUIRE_ARRAY));

$input = filter_input_array(INPUT_POST, $definitions);

if ($input['age'] === false)
{
   echo "L'età deve essere compresa tra 0 ed 80 anni";
}

// controllare gli altri valori ...

?>

Conclusioni

Filtrare i dati in input è un'operazione necessaria e di indubbia utilità per migliorare la sicurezza dei nostri sistemi. PHP 5.2 fornisce come estensione built-in la libreria Filter, che offre delle funzionalità per validare e filtrare i dati senza dover passare per moduli sviluppati manualmente e lavorando a livello SAPI (Server Application Programming Interface), quindi prima che i dati arrivino effettivamente ai nostri script PHP.

Ti consigliamo anche