Sistema completo di registrazione e login utente

In questo tutorial avanzato vedremo come creare un sistema completo di utenti registrati sul nostro sito, con l’eventuale introduzione di pagine ad accesso riservato.

La registrazione degli utenti e il sistema di login sono aspetti molto importanti per qualsiasi tipo di applicazione web. La sessione gioca un ruolo chiave in questo tipo di sistema e in questo tutorial vedremo come usare le sessioni in PHP per mantenere lo stato di login.

Per eseguire lo script abbiamo bisogno di:

  • PHP abilitato sul server
  • Database SQL
  • Discreta dimestichezza tecnica

Dovremo creare 5 oggetti principali (più il file di configurazione per il database). Suggerisco di mantenere l’ordine suggerito dal tutorial, poi una volta acquisito il metodo potrete gestire i metodi come meglio credete. Gli oggetti in questione sono:

  • Tabella ‘users’ sul database
  • Script per la registrazione (registration.php)
  • Script per il login (login.php)
  • Script per il logout (logout.php)
  • Un file che controlla la sessione utente da includere all’inizio di ogni pagina (header.php).

Cominciamo! Il primo oggetto da creare è una tabella sul database nella quale verranno immagazzinati i dati degli utenti. Portiamoci sul nostro phpmyadmin (o servizio simile) e lanciamo la seguente query:

CREATE TABLE `users` (
`user_id` mediumint(8) NOT NULL auto_increment,
`username` varchar(25) NOT NULL default '',
`user_password` varchar(32) NOT NULL default '',
`user_email` varchar(255) NOT NULL default '',
PRIMARY KEY (`user_id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=1;

Bene, ora passiamo al file per gestire la sessione e la connessione al database.

Prima di procedere, però, dobbiamo creare un file con le nostre impostazioni per collegarci al database. È molto pratico generare un file singolo per poi poterlo includere in tutti i documenti che necessitano una connessione con il db.

Questo file lo chiameremo config.php e conterrà il seguente codice che chiaramente dovrete editare con i vostri parametri.

<?php
$db_host = 'localhost';
$db_name = 'test';
$db_user = 'root';
$db_pass = 'your_password';

Nel file config.php definiamo anche le variabili relative al cookie. I cookies sono piccole quantità d’informazioni memorizzate dal browser nel computer dell’utente. PHP offre funzioni che permettono di memorizzare informazioni in questi cookies e successivamente di recuperarle.

La funzione che memorizza le informazioni nel cookie è la seguente :

setcookie("nome","valore", data_scadenza, percorso, dominio)
  • nome: dobbiamo scegliere un nome per il cookie, io ho messo test_session
  • valore: il parametro sarà valorizzato dallo script con i dati estratti dal database
  • data scadenza: valore che determina la scadenza del cookie espressa in secondi. Nell’esempio il cookie scadrà dopo un’ora dalla sua creazione.
  • percorso: lasciando ‘/’ il cookie sarà valido per tutte le cartelle del dominio
  • dominio: è preferibile usare la forma .tuodominio.com, se impostate www.tuodominio.com, il cookie sarà valido solo nel sottodominio www

Detto questo, aggiungete le vostre impostazioni nel file config.php

$cookie_name = 'test_session';
$cookie_time = 3600;
$cookie_path = '/' ;
$cookie_domain = 'localhost';

Ok ragazzi, è venuto il momento di creare il prossimo file, header.php chiamato a gestire la nostra sessione utente.

È abbastanza illogico controllare la sessione in ogni files, quindi la situazione più logica è gestirla in un unico file che andremo a includere in tutte le nostre pagine.

Nel codice del nostro header.php noteremo la funzione ob_start, che ci servirà per ottimizzare l’esecuzione dello script con un discreto miglioramento della velocità nel caricamento della pagina.
Ob sta per Output Buffering, e il suo scopo è di inviare ogni dato dello script in una sorta di memoria temporanea, il bufffer appunto.

Molto importante la funzione session_start() che crea o riprende una sessione sulla base di un identificativo unico.

<?php
ob_start();
session_start();
//connessione database
$db = new PDO('mysql:host='.$db_host.';dbname='. $db_name, $db_user, $db_pass);
if(!isset($_SESSION['logged_in'])) 
{
 $username = 'Guest';
 //controlla cookie
 if(isset($_COOKIE[$cookie_name]))
 {
  //estrae username e password dal cookie
 list($user, $pass) = explode('|', $_COOKIE[$cookie_name]);
 //preleva username e password dal database
 $select = $db->prepare("SELECT `user_password` FROM users where username = :name");
 $select->bindParam(':name', $user, PDO::PARAM_STR);
 $select->execute();
 $row = $select->fetchColumn();
 if($row)
 {
  //confronta i due dati e se ok apre sessione
  if($row == $pass)
  {
   $_SESSION['logged_in'] = 1;
   $_SESSION['username'] = $user;
   $_SESSION['password'] = $pass;
   $username = $_SESSION['username']; 
  }
 }
 }
}
else $username = $_SESSION['username'];
?>

Lo script controllerà se l’utente è loggato o meno. Nel caso non esistesse la sessione utente, andiamo a controllare se si tratta di un utente di ritorno che a suo tempo ha impostato il cookie per il login automatico. In quel caso controlliamo la veridicità delle informazioni salvate nel cookie facendo una query nel database e confrontando i dati.

Ogni volta che vorremo mettere dei contenuti riservati agli utenti registrati nelle nostre pagine dovremo avere l’accortezza di strutturare il codice secondo questa logica

<?php
if (isset($_SESSION['logged_in'] ))
{
  // contenuto per utenti registrati
}
else
{
  // contenuto per gli ospiti
}
?>

Passiamo al file registration.php

<?php
include('config.php');
include('header.php');
//controlla se l'utente è già loggato
if($_SESSION['logged_in'] == 1) header('Location: http://www.miosito.com');
$submit = isset($_POST['submit']) ? true : false;
if($submit)
{
 $error = array();
 // controllo dati immessi dall'utente
 if(empty($_POST['username']) || empty($_POST['email']) || empty($_POST['psw']) || empty($_POST['psw-repeat']))
 {
  $error[] = 'Per favore compila tutti i campi richiesti';
 }
 // controllo se il nome utente è già presente nel database
 $select = $db->prepare("SELECT user_id FROM users where username = :name");
 $select->execute(array(':name' => $_POST['username']));
 $row = $select->fetch();
 if($row != false) $error[] = $error[] = 'Il nome scelto è già presente nel database';
 // verifica conferma password
 if($_POST['psw'] != $_POST['psw-repeat']) $error[] = 'Per favore controlla la password scelta';
 if(empty($error))
 {
  // registriamo l'utente nel database
  $password = 
  $sql = "INSERT INTO users (username, user_password, user_email) VALUES (:username, :password, :email)";
  $reg = $db->prepare($sql);
  $reg->execute(array(
    ':username' => $_POST['username'],
    ':password' => md5($_POST['psw']),
    ':email'    => $_POST['email']
  ));
  // avvisa utente
  echo '<h2>Registrazione effettuata, conserva questi dati per il login</h2>';
  echo '<p><b>Username</b>:'.$_POST['username'] . '</p>';
  echo '<p><b>Password</b>:'.$_POST['psw'] . '</p>';
 }
 else
 {
  echo '<b>Sono presenti i seguenti errori</b>';
  foreach ($error as $e)
  {
   echo '<p>'.$e.'</p>';
  }
 }	
}
// il modulo non è stato inviato
else
{
 ?>
 <form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post">
   <div class="input-group">
    <label>Username</label>
    <input type="username" placeholder="Scegli un username" name="username">
   </div>
   <div class="input-group">   
    <label>Email</label>
    <input type="email" placeholder="La tua email" name="email">
   </div>
   <div class="input-group">
    <label>Password</label>
    <input type="password" placeholder="Scegli una password" name="psw">
   <div class="input-group">
    <label>Repeat Password</label>
    <input type="password" placeholder="Conferma Password" name="psw-repeat">
   </div>
    <div class="clearfix">
      <button type="button"  class="cancelbtn">Cancel</button>
      <button type="submit" name="submit" class="signupbtn">Registrati</button>
    </div>
 </form>
 <?php
}
?>

Un po’ lunghetto vero ? Beh quando ho intitolato questo articolo non ho scelto a caso l’attributo “completo”! Lo script per la registrazione non lascia nulla al caso.

Controlla la validità dei campi, verifica se abbiamo scelto un nome utente già utilizzato nel database e ricorda all’utente i dati per il login. Avremmo potuto anche spedire una mail con il riepilogo, ma in tutta sincerità ho cambiato sistema operativo e devo ancora finire di configurare il server locale.

Passiamo al prossimo step, il file login.php. Faremo un semplice form con due campi, username e password, più un checkbox da spuntare se vogliamo che i nostri dati siano memorizzati nel cookie e riprendere automaticamente la sessione al prossimo accesso.

<?php
include('config.php');
include('header.php');
//controlla se la sessione è già attiva
if(isset($_SESSION['logged_in']))
{
 header('Location: index.php');
} 
$submit = isset($_POST['submit']) ? true : false;
if($submit)
{
 $error = array();
 if(!empty($_POST['username']) && !empty($_POST['psw']))
 {
  $select = $db->prepare("SELECT username, user_password FROM users WHERE username = :name AND user_password = :psw");
  $select->execute(array(':name' => $_POST['username'], ':psw' => md5($_POST['psw'])));
  $row = $select->fetch(PDO::FETCH_ASSOC);
  if(!$row) $error[] = 'Login fallito ! Verifica se hai inserito correttamente username e password';
 }
 else $error[] = 'Per favore compila tutti i campi';
 // se tutto ok effettuo il login altrimenti stampo errori
 if(empty($error))
 {
  $_SESSION['logged_in'] = 1;
  $_SESSION['username'] = $row['username']; 
  $_SESSION['password'] = $row['user_password']; 
  //se abbiamo spuntato il campo ricordami creo il cookie
  if(isset($_POST['remember_me']))
  {  
   $cookie_value = $row['username'].'|'. $row['user_password'];
   setcookie($cookie_name, $cookie_value, time() + $cookie_time, $cookie_path, $cookie_domain);   
  }
  //reindirizza verso la tua homepage
  header('Location: index.php');
 }
 else
 {
  echo '<h2>Sono presenti i seguenti errori</h2>';
  foreach ($error as $e)
  {
   echo '<p>'.$e.'</p>';
  } 	
 }
}
?>
 <form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post">
   <div class="input-group">
    <label>Username</label>
    <input type="username" placeholder="Il tuo username" name="username">
   </div>
   <div class="input-group"> 
    <label>Password</label>
    <input type="password" placeholder="La tua password" name="psw">
   <div class="input-group">
    <label>Ricordami</label>
    <input type="checkbox" name="remember_me" value="1">
   </div>
    <div class="clearfix">
      <button type="button">Cancel</button>
      <button type="submit" name="submit">Login</button>
    </div>
 </form>

Lo script del login controlla innanzitutto se l’utente è già loggato, in tal caso lo reindirizzerà verso l’homepage del sito. Successivamente si controlla se il modulo è stato inviato, verificando se effettivamente esiste nel database un utente con le credenziali fornite. A quel punto possiamo salvare i dati dell’utente nella sessione.

Nel caso della spunta sul checkbox “ricordami”, lo script provvederà a creare il tanto decantato cookie, con i parametri che abbiamo impostato nel file precedente.

E anche la parte del login è finita. Adesso è arrivato il momento dell’ultimo file, il logout.
Il codice del file logout.php è molto semplice, non farà altro che chiudere la sessione, attraverso la funzione session_destroy() e cancellare il cookie, impostando una data passata.

time() - 1

Ecco il codice completo :

<?php
include('config.php');
include('header.php');
if(!isset($_SESSION['logged_in']))
{
header('Location: index.php');
}
else
{
setcookie($cookie_name, '', time() + $cookie_time, $cookie_path, $cookie_domain);
session_destroy();
header('Location: index.php');
}
?>

Finito, adesso abbiamo a disposizione un sistema quasi completo di utenti registrati sul nostro sito web. Dico quasi perché si potrebbero aggiungere molte altre funzioni, come ad esempio la richiesta per il reset della password o la possibilità di caricare un avatar. Ma per adesso credo che sia sufficiente.

Testate il sistema sul vostro server e se avete problemi chiedete nei commenti, sarò felicissimo di aiutarvi.

Grazie a tutti per l’attenzione, alla prossima !

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *