Questo metodo si basa sulla capacità dell'interprete PHP di gestire le variabili di "sessione".
Le variabili di sessione vengono generate dagli script e sono variabili globali visibili a qualsiasi altro script. Questa azione avviene in collaborazione con il client. Infatti in caso di creazione di una nuova sessione l'interprete PHP invia al browser un header HTTP che fa la richiesta di scrittura di un "cookie".
I "cookies" sono file di testo memorizzati nell'area di cache del browser (la cartella temporanea in cui vengono memorizzate le pagine visitate) che servono come memoria di stato per il server.
Quando un "cookie" viene scritto da un server web nella cache del client, ad ogni successiva richiesta del browser verso quel server vengono inviati anche i "cookies" che il server aveva in precedenza impostato.
In questo modo si crea una memoria di stato usata dal server ma archiviata nel client e che viaggia tra il client e il server web ad ogni richiesta di pagina verso quel server.
L'archiviazione dei cookies è facoltativa da parte del browser (si può disabilitare in modo completo o abilitare selettivamente per dominio) tuttavia in caso di cookies disabilitati i siti web che creano dinamicamente le pagine non sono in grado di funzionare.
Le variabili di sessione sono quindi "materialmente" archiviate nel client ma ripetute ad ogni richiesta e quindi viste dagli script di sessione come variabili di ambiente contenute nell'array associativo $_SESSION a cui gli script hanno accesso in lettura e scrittura.
Il vantaggio di questa tecnica è che ci si svincola dalle regole della autenticazione HTTP (ad esempio il form di richiesta dati può essere personalizzato, si possono combinare le informazioni di base nome-utente e password con altre informazioni) ma lo svantaggio è una maggiore complessità degli script.
Ogni pagina autenticata deve contenere la verifica della sessione. All'inizio della esecuzione le variabili di sessione vanno aperte:
<?php
session_start();
?>
Se si vuole subordinare un'azione della pagina all'esistenza di una autenticazione si deve prevedere una variabile di sessione la cui esistenza prova che la sessione è aperta.
Nell'esempio che segue la variabile di ambiente si chiama utente, contiene il nome utente ed è vista come un elemento dell'array di sessione ($_SESSION).
Se l'elemento utente esiste l'autenticazione è soddisfatta e si può procedere con la pagina normale mentre se non esiste non è ancora stata fatta l'autenticazione e quindi la pagina mostra solo la possibilità di autenticarsi (link a login_nodb.php).
Diversamente dall'autenticazione basic http in questo caso è possibile effettuare un logout rimuovendo lo stato di sessione (link a logut_nodb.php).
<?php
session_start();
if (isset($_SESSION['utente'])){
?>
Utente riconosciuto<b> <?php echo $_SESSION['utente']; ?></b>
<a href="logout_nodb.php">logout</a><br>
<?php
}
else {
?>
Non sei riconosciuto,
è possibile <a href="login_nodb.php">autenticarsi</a>
<?php
}
?>
Nel caso in cui l'utente non si sia ancora autenticato, Lo script gli mostra il link per accedere alla pagina di autenticazione. Questo link lancia la pagina di login.
Se la variabile login (passata con il metodo post) non possiede alcun valore viene presentato un form per l'inserimento di nome utente e password e viene settata la variabile login. L'azione di submit del form lancia la pagina stessa che però ora ha la variabile 'login' settata e quindi prende la strada della verifica. Come nel precedente esempio http per semplicità la verifica viene fatta cercando i dati immessi in un array interno.
Se la verifica ha successo vengono eseguite le due seguenti azioni:
Nella variabile utente viene memorizzato il valore ricevuto dal form. In questo modo tutte le pagine successivamente aperte trovano questa variabile già impostata.
Redirezione alla pagina che aveva chiesto l'autenticazione. In questo modo si torna automaticamente alla pagina principale ma ora in stato autenticato, quindi la pagina viene ricaricata in modo diverso. Affinchè la redirezione funzioni è indispensabile che non sia preceduta da alcuna operazione di output perchè la redirezione è un header.
L'algoritmo si basa su un automa descritto dalla tabella seguente:
Stato | $_SESSION['utente'] | $_POST['login'] | Descrizione stato | Comportamento atteso |
1 | Non esiste | Non esiste | Fase: dati di identificazione | Viene presentato il form: l'utente lo compila ed invia (alla stessa pagina) i dati |
2 | Non esiste | Esiste | Fase: accertamento e selezione | La pagina riceve i dati dal form ed accerta l'esistenza dell'utente. In caso di fallimento viene impedito di proseguire, altrimenti si imposta la variabile di sessione utente. |
3 | Esiste | Non esiste | Fase: mantenimento dello stato | L'utente è autenticato e può accedere alla pagina. |
Se la verifica fallisce viene rimossa la variabile login e avviene una redirezione alla pagina stessa in modo che ripresenti il form di richiesta.
<?php
session_start();
if (!isset($_POST['login'])) {
?>
<html>
<head>
<title>Autenticazione</title>
</head>
<body>
<form name="formlog" method="post" action="<?php echo $_SERVER['PHP_SELF']?>">
<input name="login" type="hidden" id="login" value='login'>
<input name="utente" type="text" id="utente">
<input name="password" type="password" id="password">
<input type="submit" name="Submit" value="Invia">
</form>
</body>
</html>
<?php
} else {
//controlla autorizzazioni
$user_id = strtolower($_POST['utente']);
$pwd = $_POST['password'];
$utenti = array(
'user1' => 'qwerty',
'user2' => 'asdfgh'
);
if (isset($utenti["$user_id"])) {
if ($utenti["$user_id"] == $pwd) {
$_SESSION['utente'] = $_POST['utente'];
header("Location: sessione.php");
} else {
unset($_POST['login']);
header("Location: login_nodb.php");
}
} else {
unset($_POST['login']);
header("Location: login_nodb.php");
}
}
?>
Lo script di login apre la sessione per vedere le variabili di sessione. La prima volta che viene lanciato l'elemento $_POST['login'] sicuramente non esiste quindi viene mostrato il form di richiesta del nome utente e password.
Le caratteristiche di questo form sono:
Il campo password è oscurato (type=password)
Usa il metodo POST
Esiste un campo nascosto (type=hidden) che assegna alla variabile login un valore qualsiasi
Il submit rilancia lo stesso script
Nel successivo rilancio però la variabile $_POST['login'] esiste quindi lo script non spedisce il form ma esegue l'azione di verifica.
La verifica si basa sul confronto con i valori contenuti in un array interno. Se il confronto da esito positivo viene creata la variabile di sessione $_SESSION['utente'] con il valore del nome utente e viene effettuata una redirezione alla pagina che aveva richiesto il login. Se il confronto fornisce esito negativo viene rimossa la variabile di 'login' e redirezionata alla pagina di login stessa che in assenza della variabile di login ripresenta il form.
L'utente vede questa situazione come un fallimento del login.
Questo comportamento di redirezione è, ad esempio, quello che si verifica quando, nella casella di posta elettronica, si riceve un messaggio di avviso relativo ad un post inserito in un forum. Il messaggio contiene un link che manda direttamente alla lettura del post ma percorrendo quel link ci si trova nella pagina di login (redirezione automatica verso un login a causa della mancanza di una variabile di sessione). Inserendo nome utente e password corretti si apre automaticamente la pagina contenente il post richiesto (redirezione automatica verso la pagina richiesta a causa del successo del login).
La pagina di logout rimuove la variabile di sessione utente e redireziona alla pagina chiamante che però viene rieseguita senza autenticazione.
<?php
session_start();
session_destroy();
header("Location: Sessione.php.php");
?>
In questi esempi, più realistici, le informazioni di autenticazione (nome utente e password cifrata) sono contenute in una banca dati. In questo modo si ottiene una gestione più flessibile e più sicura.
Gestione della banca datiSi supponga di archiviare in una tabella tutte le coppie username/password degli utenti ammessi. Con una semplice query sarà possibile verificare se i dati ricevuti sono presenti in questa tabella e di qui concedere o meno l'accesso alla pagina.
Per garantire riservatezza alle password memorizzate è bene che nella tabella queste siano memorizzate in forma criptata e non in chiaro. Per questo scopo sono disponibili la funzione SQL password() e la funzione PHP md5().
Nel primo caso la criptazione è affidata a mysql, esempio:
// la tabella utenti ha attributi username e password e si vuole
// inserire i dati di un utente memorizzati in variabili PHP $u e $p:
$query="INSERT INTO utenti VALUES ($u,PASSWORD($p))";
// la tabella utenti ha attributi username e password e si vuole
// verificare se esiste un utente i cui dati sono nelle
// variabili PHP $u e $p:
$query="SELECT * FROM utenti WHERE username=$u AND password=PASSWORD($p)";
Nel secondo caso la criptazione è affidata a php, esempio:
// la tabella utenti ha attributi username e password e si vuole
// inserire i dati di un utente memorizzati in variabili PHP $u e $p:
$query="INSERT INTO utenti VALUES ($u,".md5($p).")";
// la tabella utenti ha attributi username e password e si vuole
// verificare se esiste un utente i cui dati sono nelle
// variabili PHP $u e $p:
$query="SELECT * FROM utenti WHERE username=$u AND password=".md5($p);
Di seguito è mostrato il procedimento di generazione di questa tabella:
DROP TABLE IF EXISTS utenti\g
CREATE TABLE utenti(
username CHAR(255) NOT NULL,
password CHAR(255) NOT NULL,
descrizione CHAR(255) NOT NULL,
PRIMARY KEY Pk (Username)
)\g
INSERT INTO utenti VALUES('manut',PASSWORD('1QazXsW2'),'superuser')\g
INSERT INTO utenti VALUES('user1',PASSWORD('2wSxCdE3'),'utente 1')\g
INSERT INTO utenti VALUES('user2',PASSWORD('3EdCvFR4'),'utente 2')\g