PHP+MYSQL: alcune soluzioni con password_hash, select ed altro

 

Riporto alcuni semplici esempi utili a risolvere alcuni casi nell'uso di PHP con MySQL. Sono corredati da istruzioni di massima con parametri di fantasia che, ovviamente, vanno adattati alle proprie esigenze. Pur nella semplicità, gli esempi richiedono un minimo di conoscenza di PHP.

Proteggere password inserite con password_hash() e recuperarle con password_verify()

La funzione citata permette (solo con versioni PHP>= 5.5.0) di gestire in modo comodo l'inserimento ed il recupero di una stringa di caratteri immessa in un campo del database con funzione di password protetta o comunque laddove ci sia necessità di fare hashing con i dati immessi. Il metodo usato è quello hash con l'aggiunta di crittografia SALT (in sostanza viene aggiunta un'altra stringa casuale alla password prima dell'hash). Il tutto viene generato automaticamente secondo i parametri passati con una evidente semplificazione ed è compatibile con crypt() sempre di PHP. La funzione può usare anche l'algoritmo bcrypt.  L'alternativa a questa comoda funzione è creare appositamente delle routine con altri comandi di PHP che forniscono più o meno lo stesso risultato ma che necessitano di una certa conoscenza delle cose da fare (specie nella generazione di un random SALT). Utili, in tal caso, sono alcuni esempi di questo genere che si trovano su Internet ma non sempre in sintonia con le proprie esigenze. La pagina del manuale ufficiale è QUI. E' tutto abbastanza chiaro. Le opzioni password_default e password_bcrypt richiedono però una precisazione. Non è ben chiara la differenza se non che allo stato attuale con la prima viene usato l'algoritmo bcrypt di default mentre la seconda specifica direttamente l'uso dell'algoritmo crypt blowfish. Cioè 'default'  sembra essere stato lasciato aperto dagli sviluppatori di PHP per una possibilie implementazione futura per un altro algoritmo. Insomma, comunque scegliendo tra i due si conferisce alla password una sicurezza di buon livello. Anche l'opzione 'cost' richiede un chiarimento. La scelta di default è 10. Incrementarla, oltre a fornire più efficienza, aumenta però i tempi di gestione, il che vuol dire, ad esempio, che se scegliamo 11 al posto di 10 i tempi di generazione quasi si raddoppiano (un secondo d'attesa diventano due e così via) per cui la scelta dipende dall'hardware usato. Valutare quindi di conseguenza. Passiamo ad un blocco d'struzioni di base, come esempio. Si presuppone che in MySQL si abbia una tabella 'users' con un campo password 'pwd' della lunghezza appropriata (meglio 255 caratteri) e settato a VARCHAR. In una pagina PHP l'hashing avverrà, dopo aver eventualmente trasferito le variabili dei dati immessi con  _POST,  scrivendo:

<?

$password_save = password_hash($password, PASSWORD_BCRYPT, array('cost' => 12 ));
$db = mysql_connect("localhost", "pippo", "xxxx");
mysql_select_db("database",$db);
$insertpwd="INSERT INTO users (surname,name,username,pwd) values ('$surname','$name','$username','$password_save')";
mysql_query($insertpwd);

?>

Invece il recupero della password e la sua collisione con la password immessa dall'utente per l'accesso avviene con la funzione password_verify()  (pagina del manuale di PHP). In pratica, dopo che l'utente ha immesso in una FORM la sua password questa viene recuperata e poi confrontata in modo analogo a queste istruzioni d'esempio:

<?

$password=$_POST['password'];

$db = mysql_connect("localhost", "pippo", "xxxx");
mysql_select_db("database",$db);
$resultpwd=mysql_query("SELECT id,pwd FROM users", $db);
while (list($id,$pwd) = mysql_fetch_row ($resultpwd))
{
$hash=$pwd;

password_verify($pwdcriterio, $hash)

 

  }

?>

In pratica il loop 'while' legge le righe delle password della tabella users inserite nel campo 'pwd' finchè questa non collima con quella immessa dall'utente. Notare la presenza anche di un campo id nel recupero. E' utile perchè permetterà successive operazioni sulle tabelle in quanto punta ad un record univoco e corrisponde ad un campo id nella tabella users di natura auto_increment. Ovviamente se volete maggiore sicurezza negli accessi potete usare i comandi descritti anche per fare hashing e recupero sull'username, ad esempio.

Passiamo ora ad altre soluzioni che interessano in genere la presentazione di dati o altri trucchetti per risolvere alcuni intoppi sia nella veste grafica che nell'uso di un database MySQL gestito con PHP.

Come usare il comando <select> <option>  in alcune situazioni

Il comando <select> permette di gestire un menu con delle opzioni su singola riga per effettuare delle scelte. In alcuni casi è però comodo per l'utente visualizzare contemporaneamente sulla stessa riga più informazioni della scelta da effettuare. Prendiamo il caso banale di una rubrica. L'operazione supposta è di cambiare i dati informativi di un nominativo in rubrica contenuti in un'altra tabella, ovviamente relazionata mediante un campo (idnome). E' piu' comodo scegliere in tal caso avendo magari davanti oltre al classico cognome anche il nome, l'indirizzo, ecc. se non altro per evitare dubbi in caso di omonimie. Per scegliere in modo univoco quel nominativo in altre tabelle in modo più sicuro di una scelta fatta solo sul cognome bisognerà aggiungere in <option> un value all'identificativo univoco, in questo caso idnome. Dopodichè impostiamo il comando in modo tale da far vedere le informazioni sulla stessa riga. Le istruzioni di base in una pagina PHP contengono sia codice php che html (sotto forma di FORM) e saranno analoghe a questo esempio:

<?

$db = mysql_connect("localhost", "pippo", "xxxx");
mysql_select_db("rubrica",$db);
$result=mysql_query("SELECT * FROM nominativi", $db);
echo "<FORM action=vedinominativo.php method=post>";
echo "<select name='criterioscelta' size='20' style='font-size: 16px; font-family: Helvetica;font-weight: 700; color:#0000FF;width:800px;'>";
 
while (list($idnome,$surname,$name,$address)= mysql_fetch_row($result))
 {

    echo "<option value=$idnome>nominativo: $surname $name indirizzo: $address</option>";
                    
    }

echo "</select>";

echo "<INPUT TYPE=submit name='SCELTA' value='ESTRAI' style='font-size: 15px; font-family: Helvetica;font-weight:700; color:#C00000;'>";

echo "</FORM>";

?>

L'esempio apre la tabella 'nominativi' del database 'rubrica' e l'inserisce in una FORM html dove il comando <select> estrae in successione i dati della tabella grazie al loop di while, presentandoli in un menu scorrevole la cui formattazione è data da size=20 (cioè 20 righe visibili) e altri parametri in style tra cui spicca width=800px che fissa la larghezza della finestra visibile in pixel. Il punto fondamentale è dato dall'opzione value=$idnome in <option> la quale permette che il parametro memorizzato nella scelta sia quello univoco della chiave 'idnome' della tabella, anche se l'utente non lo vede. Notare che sulla riga dell' <option> possono essere mischiate sia le stringhe delle variabili sia stringhe di caratteri normali per rendere più fruibili le informazioni. L'utente cliccando sul nominativo scelto lo evidenzia e con il tasto di scelta in basso (INPUT TYPE=submit) aprirà la pagina .php richiesta. La pagina aperta (vedinominativo.php) con il FORM recupererà le informazioni _POST da una tabella 'contatti' secondo quanto dato con il <select>  e relative al nominativo univocamente cercato attraverso l'idnome, passato direttamente da value in <option>. Un esempio semplice è qui fornito:

<?
$change=$_POST['criterioscelta'];
$db = mysql_connect("localhost", "pippo", "xxxx");
mysql_select_db("rubrica",$db);
$result=mysql_query("SELECT * FROM contatti WHERE idnome='$change'", $db);

?>

In sostanza: il criterio di scelta passato dal <select> alle istruzioni successive non è più dato dalla stringa di caratteri contenuta tra <option> e </option> ma dal parametro value= (nell'esempio value=$idnome) mentre, da un punto di vista grafico e pratico, la scelta risulterà più completa.

Impedire la troncatura delle variabili memorizzate in un INPUT TYPE=hidden nel caso di stringhe contenenti spaziatura

Sembra banale ma in realtà è un problema molto fastidioso. Se in una FORM vengono assegnate ad un INPUT TYPE=hidden delle variabili contenenti stringhe di caratteri con aggiunta di spazi, il valore trasmesso da INPUT viene troncato al primo spazio trovato. Per esempio prendiamo istruzioni come:

<?

 

$row=mysql_fetch_array($result);

echo "<INPUT TYPE='hidden' name='changeaddress' value='$row[address]'>";

?>

dove abbiamo assegnato dentro una FORM il valore restituito da una ricerca in un database. Se il valore della variabile 'address' contiene spazi (come in 'Via della Vittoria') a sua volta 'changeaddress' usato dopo restituirà solo 'Via' e non l'intera stringa.  Per ovviare, sarà sufficiente usare gli apici ' ' nell'inserire i valori in INPUT TYPE proprio come nell'esempio sopra riportato.

 

Cancellare tutte le tabelle di un database con PHP

Qualora sia necessario, per svariati motivi, cancellare tutte le tabelle di un database MySQL attraverso uno script PHP, si può seguire questo esempio:

<?
$conn= mysql_connect('localhost','pippo','xxxx');
if ($conn <= 0) {
die("Errore nella connessione");
  }
$res = mysql_select_db('database', $conn);
if ($res == false) {
 die("Errore nella selezione del db");
 }
$res = mysql_query("SHOW TABLES");
while($tab = mysql_fetch_array($res))
    mysql_query("DROP TABLE " . $tab[0]);
mysql_free_result($res);
mysql_close($conn);
?>

L'esempio produce anche dei warning in caso di errori.