- Gestire il workflow di registrazione a più fasi.
- Generare e gestire token di sicurezza univoci.
- Implementare logiche di aggiornamento record (UPDATE) condizionali.
Il processo di Attivazione dell'Utente
Un account "appena creato" deve essere in uno stato di sospensione. Per gestire questo processo, aggiungiamo due concetti chiave al nostro sistema:
| Elemento | Scopo |
|---|---|
| Colonna "attivo" | Un valore booleano (0 o 1) nel DB che indica se l'utente può fare login. |
| Token | Una stringa casuale alfanumerica inviata via mail per identificare la richiesta. |
| Link di attivazione | Una URL che punta a uno script PHP passando il token come parametro GET. |
LABORATORIO
Implementazione Double Opt-In
- Modifica alla tabella
utenti(vedi step 1). - Conoscenza della funzione
bin2hex(random_bytes(16))per generare il codice.
1 Aggiornamento Database
Dobbiamo aggiungere i campi per gestire lo stato e il codice di verifica:
ALTER TABLE utenti
ADD COLUMN codice_conferma VARCHAR(100),
ADD COLUMN attivo TINYINT(1) DEFAULT 0;
2 Registrazione con invio codice (registrazione.php)
Modifichiamo la logica di inserimento per generare il token.
<?php
require "config.php";
if ($_SERVER["REQUEST_METHOD"] == "POST") {
$user = $_POST['username'];
$email = $_POST['email'];
$pass_sicura = password_hash($_POST['password'], PASSWORD_BCRYPT);
// Generiamo un codice casuale univoco
$token = bin2hex(random_bytes(16));
$sql = "INSERT INTO utenti (username, email, password, codice_conferma, attivo)
VALUES (:u, :e, :p, :t, 0)";
$stmt = $pdo->prepare($sql);
if ($stmt->execute(['u' => $user, 'e' => $email, 'p' => $pass_sicura, 't' => $token])) {
// Simulazione invio email (in un server reale useremmo mail())
$link = "http://localhost/progetto/attiva.php?token=$token";
echo "Registrazione effettuata! Clicca qui per simulare l'email: ";
echo "<a href='$link'>Attiva Account</a>";
} else {
echo "Errore nella registrazione.";
}
}
?>
1. Il rischio delle Query Dirette
Se scrivessi la query inserendo direttamente le variabili, il codice sarebbe questo:
// CODICE PERICOLOSO - NON USARE
$sql = "INSERT INTO utenti (username) VALUES ('$user')";
Il problema: Se un utente cattivo nel campo username scrivesse: '); DROP TABLE utenti; --, la tua query diventerebbe:
INSERT INTO utenti (username) VALUES (''); DROP TABLE utenti; --')
Il database eseguirebbe due comandi: l'inserimento e la cancellazione totale della tabella. Questo è un attacco di SQL Injection.
2. Come funzionano i Segnaposto (:u, :e, :p)
Quando usiamo $pdo->prepare($sql) con i segnaposto, accade qualcosa di magico in due step:
| Fase | Cosa succede |
|---|---|
| Preparazione | Inviamo al database solo la "struttura" della query. Il DB capisce che deve fare un INSERT, ma non sa ancora cosa inserire. |
| Esecuzione | Inviamo i dati separatamente con execute(). Il database li tratta esclusivamente come puro testo, togliendo loro ogni potere di eseguire comandi. |
3. Vantaggi in sintesi
- Sicurezza: I dati vengono "puliti" automaticamente (sanitizzazione).
- Velocità: Se devi inserire 1000 utenti, il database analizza la query una sola volta e cambia solo i dati.
- Pulizia: Non devi impazzire con apici singoli (') e doppi (") dentro le stringhe SQL.
3 Pagina di Attivazione (attiva.php)
Questa pagina riceve il codice via GET, cerca l'utente e lo attiva.
<?php
require "config.php";
if (isset($_GET['token'])) {
$token = $_GET['token'];
// Cerchiamo l'utente con quel token
$sql = "SELECT id FROM utenti WHERE codice_conferma = :t AND attivo = 0";
$stmt = $pdo->prepare($sql);
$stmt->execute(['t' => $token]);
if ($stmt->rowCount() > 0) {
// Utente trovato! Lo attiviamo e cancelliamo il token
$update = "UPDATE utenti SET attivo = 1, codice_conferma = NULL WHERE codice_conferma = :t";
$pdo->prepare($update)->execute(['t' => $token]);
echo "<h2>Account attivato con successo!</h2>";
echo "<p>Ora puoi effettuare il <a href='login.php'>Login</a>.</p>";
} else {
echo "Codice non valido o account già attivo.";
}
} else {
echo "Accesso non consentito.";
}
?>
4 Esercitazione: Protezione del Login
Task: Ora che abbiamo il campo attivo, dobbiamo modificare la futura pagina login.php.
Non basta più controllare che la password sia corretta; nella query di login dobbiamo aggiungere una condizione: l'utente deve avere attivo = 1.
- Prova a scrivere la query SQL che seleziona l'utente solo se lo username corrisponde E il campo attivo è uguale a 1.