Guida Guida per creare un sistema di login e registrazione in php e mysql

Stato
Discussione chiusa ad ulteriori risposte.

Rather

Utente Emerald
24 Dicembre 2011
995
110
237
637
Ultima modifica da un moderatore:
Ciao, volevo fare questa guida così ho deciso di farla. Se non vi risulta utile ditelo :sisi:

1- Prima di tutto bisogna creare il proprio sito. (Un servizio gratuito che permette di fare ciò è Altervista)

2- Creare un database. (Se utilizzate Altervista vi basterà utilizzare i vostri dati per entrare nel servizio e successivamente cliccare su "AlterSito" --> "Database", poi cliccare su "Ottieni gratis". Successivamente per accedervi vi basterà andare su "Tools" --> "phpMyAdmin")

3- Creare file con questi nome e queste estensioni con all'interno il corrispettivo codice.
registrazione.php:
PHP:
<?phpinclude('core.php');if(isset($_POST['register'])) {    $username = isset($_POST['username']) ? clear($_POST['username']) : false;    $password = isset($_POST['password']) ? clear($_POST['password']) : false;    $email = isset($_POST['email']) ? clear($_POST['email']) : false;    if(empty($username) || empty($password) || empty($email)) {        echo 'Riempi tutti i campi.<br /><br /><a href="javascript:history.back();">Indietro</a>';    } elseif(strlen($username) > 16) {        echo 'Username troppo lungo. Massimo 16 caratteri.<br /><br /><a href="javascript:history.back();">Indietro</a>';    } elseif(strlen($password) < 6 || strlen($password) > 20) {        echo 'Lunghezza della password non valida. Minimo 6 caratteri e massimo 20.<br /><br /><a href="javascript:history.back();">Indietro</a>';    } elseif(!filter_var($email, FILTER_VALIDATE_EMAIL)) {        echo 'Indirizzo email non valido.';    } elseif(strlen($email) > 60) {        echo 'Lunghezza dell\'indirizzo email non valida. Massimo 60 caratteri.<br /><br /><a href="javascript:history.back();">Indietro</a>';    } elseif(mysql_num_rows(mysql_query("SELECT * FROM users WHERE username LIKE '$username'")) > 0) {        echo 'Username già in uso. Sei pregato di sceglierne un altro.<br /><br /><a href="javascript:history.back();">Indietro</a>';    } elseif(mysql_num_rows(mysql_query("SELECT * FROM users WHERE email LIKE '$email'")) > 0) {        echo 'Indirizzo email già in uso. Sei pregato di sceglierne un altro.<br /><br /><a href="javascript:history.back();">Indietro</a>';    } else {        $password = md5($password);        $ip = $_SERVER['REMOTE_ADDR'];        if(mysql_query("INSERT INTO users (username, password, email, reg_ip, last_ip, reg_date) VALUES ('$username','$password','$email','$ip','$ip',UNIX_TIMESTAMP())")) {            echo 'Registrazione andata a buon fine.';        } else {            echo 'Errore nella query: '.mysql_error();        }    }} else {    ?>    <form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="POST">        <label>Username: <input type="text" name="username" required maxlength="16" /></label><br />        <label>Password: <input type="password" name="password" required maxlength="20" /></label><br />        <label>Email: <input type="email" name="email" required maxlength="60" /></label><br /><br />        <input type="submit" name="register" value="Registrati" />    </form>    <?php}?>

Login:
PHP:
<?phpinclude('core.php');if(isset($_POST['login'])) {    $username = isset($_POST['username']) ? clear($_POST['username']) : false;    $password = isset($_POST['password']) ? clear($_POST['password']) : false;    if(empty($username) || empty($password)) {        echo 'Riempi tutti i campi.<br /><br /><a href="javascript:history.back();">Indietro</a>';    } elseif(mysql_num_rows(mysql_query("SELECT * FROM users WHERE username LIKE '$username'")) == 0) {        echo 'Username non trovato.<br /><br /><a href="javascript:history.back();">Indietro</a>';    } else {        $password = md5($password);        $ip = $_SERVER['REMOTE_ADDR'];        if(mysql_num_rows(mysql_query("SELECT * FROM users WHERE username LIKE '$username' AND password='$password'")) > 0) {            $username = mysql_result(mysql_query("SELECT username FROM users WHERE username LIKE '$username'"), 0);            $userid = mysql_result(mysql_query("SELECT id FROM users WHERE username LIKE '$username'"), 0);            mysql_query("UPDATE users SET last_login='".time()."', last_ip='$ip' WHERE id='$userid'") or die(mysql_error());            $_SESSION['username'] = $username;            $_SESSION['userid'] = $userid;            header('Location: index.php');        }    }} else {    ?>    <form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="POST">        <label>Username: <input type="text" name="username" required maxlength="16" /></label><br />        <label>Password: <input type="password" name="password" required maxlength="20" /></label><br />        <input type="submit" name="login" value="Accedi" />    </form>    <?php}?>

core.php:
PHP:
<?phpsession_start();$db_hostname = 'localhost';$db_username = 'INSERISCI IL TUO';$db_password = 'INSERISCI LA TUA';$db_name = 'INSERISCI NOME';
mysql_select_db($db_name, mysql_connect($db_hostname, $db_username, $db_password)) or die("Impossibile connettersi.".mysql_error());mysql_query("CREATE TABLE IF NOT EXISTS users (id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, username VARCHAR(16) NOT NULL, password VARCHAR(32) NOT NULL, email VARCHAR(60) NOT NULL, reg_ip VARCHAR(20), last_ip VARCHAR(20), reg_date INT NOT NULL, last_login INT)");function clear($var) {    return addslashes(htmlspecialchars(trim($var)));}?>

index.php:
PHP:
<?phpinclude('core.php');if(isset($_SESSION['username'])) {    $userid = $_SESSION['userid'];    $last_login = mysql_result(mysql_query("SELECT last_login FROM users WHERE id='$userid'"), 0);    echo 'Bentornato, '.$_SESSION['username'].'.<br />Il tuo ultimo login risale al giorno '.date('d-m-Y', $last_login).' alle ore '.date('H:i', $last_login);} else {    header('Location: login.php');}?>

ATTENZIONE:
Ho cercato di semplificare il tutto facendovi risparmiare di dover inserire la tabella utenti all'interno del database poiché provvederà "il codice" a fare ciò .

Ricontrollate il codice per vedere se ci sono eventuali errori e per inserire i dati del vostro database.

Naturalmente personalizzate il codide
 
Ultima modifica:
In Core non è meglio mysql_real_escape_string() invece di addslashes? Io fin ora non son riuscita a contrastare la sicurezza con l'sqlInjection .

Scusa, mi sono data la libertà di rendere più leggibile i codici senza modificarli.

Index
PHP:
<?php
include('core.php');
if(isset($_SESSION['username'])) { 
   $userid = $_SESSION['userid']; 
   $last_login = mysql_result(mysql_query("SELECT last_login FROM users WHERE id='$userid'"), 0); 
   echo 'Bentornato, '.$_SESSION['username'].'.<br />Il tuo ultimo login risale al giorno '.date('d-m-Y', $last_login).' alle ore '.date('H:i', $last_login);
 }
 else { 
   header('Location: login.php');
 }
?>

Core
PHP:
<?php
session_start();
$db_hostname = 'localhost';
$db_username = 'INSERISCI IL TUO USERNAME';
$db_password = 'INSERISCI LA TUA PASSWORD';
$db_name = 'INSERISCI IL NOME DEL DATABASE';
mysql_select_db($db_name, mysql_connect($db_hostname, $db_username, $db_password)) or die("Impossibile connettersi.".mysql_error());
mysql_query("CREATE TABLE IF NOT EXISTS users (id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, username VARCHAR(16) NOT NULL, password VARCHAR(32) NOT NULL, email VARCHAR(60) NOT NULL, reg_ip VARCHAR(20), last_ip VARCHAR(20), reg_date INT NOT NULL, last_login INT)");

function clear($var) { 
   return addslashes(htmlspecialchars(trim($var)));
}
?>


Login
PHP:
<?php
include('core.php');
if(isset($_POST['login'])) { 
   $username = isset($_POST['username']) ? clear($_POST['username']) : false;   
   $password = isset($_POST['password']) ? clear($_POST['password']) : false;   
   if(empty($username) || empty($password)) {   
        echo 'Riempi tutti i campi.<br /><br /><a href="javascript:history.back();">Indietro</a>';
   } 
    elseif(mysql_num_rows(mysql_query("SELECT * FROM users WHERE username LIKE '$username'")) == 0) {
        echo 'Username non trovato.<br /><br /><a href="javascript:history.back();">Indietro</a>';
    }
    else {           $password = md5($password); 
        $ip = $_SERVER['REMOTE_ADDR'];   
        if(mysql_num_rows(mysql_query("SELECT * FROM users WHERE username LIKE '$username' AND password='$password'")) > 0) { 
            $username = mysql_result(mysql_query("SELECT username FROM users WHERE username LIKE '$username'"), 0); 
            $userid = mysql_result(mysql_query("SELECT id FROM users WHERE username LIKE '$username'"), 0);  
            mysql_query("UPDATE users SET last_login='".time()."', last_ip='$ip' WHERE id='$userid'") or die(mysql_error());                $_SESSION['username'] = $username;  
            $_SESSION['userid'] = $userid;      
            header('Location: index.php');   
        }   
    }
}
else { 
  ?>
    <form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="POST">          <label>Username: <input type="text" name="username" required maxlength="16" /></label><br />         <label>Password: <input type="password" name="password" required maxlength="20" /></label><br />         <input type="submit" name="login" value="Accedi" />     </form> 
<?php}?>

Registrazione
PHP:
<?php
include('core.php');
if(isset($_POST['register'])){ 
    $username = isset($_POST['username']) ? clear($_POST['username']) : false;  
    $password = isset($_POST['password']) ? clear($_POST['password']) : false; 
    $email = isset($_POST['email']) ? clear($_POST['email']) : false;  
    if(empty($username) || empty($password) || empty($email)) {           echo 'Riempi tutti i campi.<br /><br /><a href="javascript:history.back();">Indietro</a>';
    } 
    elseif(strlen($username) > 16) { 
        echo 'Username troppo lungo. Massimo 16 caratteri.<br /><br /><a href="javascript:history.back();">Indietro</a>'; 
    }
    elseif(strlen($password) < 6 || strlen($password) > 20) {
        echo 'Lunghezza della password non valida. Minimo 6 caratteri e massimo 20.<br /><br /><a href="javascript:history.back();">Indietro</a>';   
    } 
    elseif(!filter_var($email, FILTER_VALIDATE_EMAIL)) { 
        echo 'Indirizzo email non valido.';    
    }
    elseif(strlen($email) > 60) {
        echo 'Lunghezza dell\'indirizzo email non valida. Massimo 60 caratteri.<br /><br /><a href="javascript:history.back();">Indietro</a>';   
    }
    elseif(mysql_num_rows(mysql_query("SELECT * FROM users WHERE username LIKE '$username'")) > 0) {        echo 'Username già in uso. Sei pregato di sceglierne un altro.<br /><br /><a href="javascript:history.back();">Indietro</a>';       }    elseif(mysql_num_rows(mysql_query("SELECT * FROM users WHERE email LIKE '$email'")) > 0) {         echo 'Indirizzo email già in uso. Sei pregato di sceglierne un altro.<br /><br /><a href="javascript:history.back();">Indietro</a>';   
    }
    else {
        $password = md5($password);
        $ip = $_SERVER['REMOTE_ADDR']; 
        if(mysql_query("INSERT INTO users (username, password, email, reg_ip, last_ip, reg_date) VALUES ('$username','$password','$email','$ip','$ip',UNIX_TIMESTAMP())")) { 
            echo 'Registrazione andata a buon fine.';               }
        else { 
            echo 'Errore nella query: '.mysql_error();             }    
    }
}
else { 
   ?>
<form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="POST"> 
    <label>Username: <input type="text" name="username" required maxlength="16" /></label>
    <br />
    <label>Password: <input type="password" name="password" required maxlength="20" /></label><br />
    <label>Email: <input type="email" name="email" required maxlength="60" /></label><br /><br />     
    <input type="submit" name="register" value="Registrati" /> 
</form>   <?php}?>
 
  • Mi piace
Reazioni: Rather
Avrai incollato direttamente il codice, è successa la stessa cosa a me, per ovviare al problema devi mandare a capo direttamente dalla textarea del form di Inforge.
 
  • Mi piace
Reazioni: Rather
Non hai evitato in nessun campo l'sql injection >.<, senza contare che usi una include al posto di require, non è un buon codice <.<
 
Hai ragione, mi sono proprio dimenticato dell'sqlinjection


Inviato dal mio iPhone 5 usando Tapatalk 2
 
mysql_query() è una funzione deprecata da PHP 5.5.
Dovresti usare PDO o altro.
md5 è un algoritmo debole, non lo userei per criptare delle passwords.
password_hash() andrebbe meglio, aggiunge da solo il sale, e ritorna un hash che comprende sale e costo.
Poi si usa password_verify() per controllare.
 
  • Mi piace
Reazioni: Scanetatore
mysql_query() è una funzione deprecata da PHP 5.5.
Dovresti usare PDO o altro.
md5 è un algoritmo debole, non lo userei per criptare delle passwords.
password_hash() andrebbe meglio, aggiunge da solo il sale, e ritorna un hash che comprende sale e costo.
Poi si usa password_verify() per controllare.

La crittografia in MD5 è comunque irreversibile, come anche in SHA1, quindi sarebbe piuttosto difficile risalire a password composta da parole "personali"...
 
  • Mi piace
Reazioni: Relyze e Rather
Debole non significa reversibile.
MD5 viene ormai usato solo per la verifica dell'integrità dei file.
MD5, come SHA1, sono algoritmi sconsigliati per la crittografia, in quanto nessuno dei due è "collision resistant".
MD5 è addiritura considerato "cryptographically broken and unsuitable for further use".
 
Ultima modifica:
Sono presenti ben 2 vulnerabilità: una per SQL injection e una per XSS.
Entrambe per colpa della funzione clear, che è troppo superficiale.
per l'XSS, è stato riscontrato che la funzione htmlspecialchars in alcune vecchie versioni di php non riconosce i caratteri in determinati charset (ad esempio UTF-7), saltando il controllo (usa htmlentities invece).
per l'SQL injection, non basta addslashes, serve anche stripslashes, e LIKE in query.... se io metto % come username, la query restituirà tutti gli utenti che sono presenti nella tabella, e basta che uno solo abbia quella password e loggherai al suo posto.
La questione di stripslashes è questa: addslashes rimpiazzerà ' con \', ma se io metto \' nella query, addslashes sostituirà come detto prima e ci sarà \\', le slash si annullano e l'apostrofo ha comunque il suo valore.

Aggiungo a dimostrazione:
Username: \' OR username LIKE %--
Password: qualunquecosa
dovrebbe garantire l'accesso con un username casuale, probabilmente il primo della tabella.
la query che viene eseguita è come fosse:
SELECT * FROM users WHERE username LIKE '\\' OR username LIKE %
a patto che ci sia almeno un utente registrato verrà selezionato dalla query.
Nella seconda query, quella con la password, stessa cosa: la password viene totalmente ignorata per via del doppio -- che commenta il resto della query.
 
  • Mi piace
Reazioni: Rather
Stato
Discussione chiusa ad ulteriori risposte.