Script login utente in php e mysql sicuro

Nell’articolo di oggi voglio approfondire con voi il perfetto sistema di login in php/mysql con uno sguardo particolare alla sicurezza del sistema.

[lightgrey_box] Attenzione: la versione di login che vedi in questo articolo è già stata migliorata grazie ai consigli degli utenti. Intanto che aspetti il nuovo articolo ti consiglio di dare un’occhiata ai commenti. Grazie per l’attenzione e per la pazienza.[/lightgrey_box]

Questo articolo vi sarà molto utile se avete intrapreso la (dura) carriera dello sviluppatore php. Nella progetta di un cms che si rispetti infatti questo step è a dir poco essenziale e fornisce ai vostri utente un accesso sicuro a tutte le aree riservate del cms come gestione articoli o gestionali vari.

01. Primo passo: Creiamo la tabella mysql

Il primo passo è quello di creare il database del sito e relativa tabella “utenti” dove andremo ad inserire i seguenti campi:

A) Id: conterrà l’id auto-incrementato dei vari utenti con accesso al cms

B) username: Il nome dell’utente (o più) che ha accesso al login.  Tipo Varchar.

C) password: La password univoca dell’utente registrato. Questo campo va filtrato usando il comando sha1 o md5. Sha1 e md5 servono per crittografare la password in modo tale che, se mai qualche intenzionato riuscisse a leggere il campo “pass” questa non potrebbe essere usata in alcun modo dato che risulta “scomposta” secondo il metodo di crittografia scelto.

Creiamo quindi la tabella all’interno del database “login”. Per farlo accediamo a phpmyadmin. A questo punto abbiamo due scelte: la prima è creare la tabella e relativi campi in modo visuale grazie a phpmyadmin; La seconda invece è quella di inserire all’interno del database “login” il seguente codice all’interno della sezione “sql” del pannello:

CREATE TABLE `login` (
`id` INT( 11 ) NOT NULL AUTO_INCREMENT ,
`username` VARCHAR( 64 ) NOT NULL ,
`password` VARCHAR( 64 ) NOT NULL ,
PRIMARY KEY ( `id` )
) ENGINE = MYISAM

INSERT INTO `login` (
`id` ,
`username` ,
`password`
)
VALUES (
NULL , 'utente', sha1( 'prova' )
);

Controllate che la tabella “utenti” sia stata creata in modo corretto. A questo punto siete pronti per il punto successivo.

02. Creazione della home

La prima pagina del vostro cms sarà ovviamente una pagina di login. solo nel caso l’utente si connetta e sia autorizzato avrà accesso alla sua sezione “privata”. Per fare il box di login creiamo lo scheletro con html e stilizziamo il tutto con i css come siamo abituati:

<?php include('config.php'); ?>
<!DOCTYPE html>
<html>
<head>

    <title>Collegati per amministrare il sito - <?php echo $sito_internet ?></title>

    <!--Pannello di gestione creato da Mel Riccardo-->
    <link href="css/admin.css" rel="stylesheet" type="text/css" />

</head>
<body>

    <form id="login" action="verifica.php" method="post">
        <fieldset id="inputs">
            <input id="username" name="username" type="text" placeholder="Username" autofocus required>
            <input id="password" name="password" type="password" placeholder="Password" required>
        </fieldset>
        <fieldset id="actions">
            <input type="submit" id="submit" value="Collegati">
            <a href="../index.php" id="back">Ritorna al sito</a>
        </fieldset>
    </form>

</body>
</html>

Come vedete nella prima riga di codice ho incluso il file config.php dal quale possiamo recuperare in modo dinamico molte informazioni (come ad esempio il nome del sito). Ecco la struttura di base del file config.php (la cui funzione principale è lo storage delle credenziali per collegarsi al database):

	//generali

	$sito_internet = "Targetweb";

	$data =(date("d-m-y"));

	$vers = "2.0";

	//URL PER HTACCESS

	$base_url = "http://localhost/tuosito";

	//connessione DB

	$host = "localhost";

	$db_user = "root";

	$db_psw = "wtargetweb";

	$db_name = "target";

La base_url ci servirà per articoli futuri quindi non preoccupatevi (per ora).

Ovviamente potete stilizzare il login box come meglio desiderate a seconda delle vostre esigenze. Ecco il css per stilizzare e usare i nuovi campi html5 che vedete nello scheletro di sopra.

  /*-------------------LOGIN--------------------*/

	#login

	{
    background-color: #fff;

    background-image: -webkit-gradient(linear, left top, left bottom, from(#fff), to(#eee));

    background-image: -webkit-linear-gradient(top, #fff, #eee);

    background-image: -moz-linear-gradient(top, #fff, #eee);

    background-image: -ms-linear-gradient(top, #fff, #eee);

    background-image: -o-linear-gradient(top, #fff, #eee);

    background-image: linear-gradient(top, #fff, #eee);  

    height: 240px;

    width: 400px;

    margin: -150px 0 0 -230px;

    padding: 30px;

    position: absolute;

    top: 50%;

    left: 50%;

    z-index: 0;

    -moz-border-radius: 3px;

    -webkit-border-radius: 3px;

    border-radius: 3px;  

    -webkit-box-shadow:

          0 0 2px rgba(0, 0, 0, 0.2),

          0 1px 1px rgba(0, 0, 0, .2),

          0 3px 0 #fff,

          0 4px 0 rgba(0, 0, 0, .2),

          0 6px 0 #fff,  

          0 7px 0 rgba(0, 0, 0, .2);

    -moz-box-shadow:

          0 0 2px rgba(0, 0, 0, 0.2),  

          1px 1px   0 rgba(0,   0,   0,   .1),

          3px 3px   0 rgba(255, 255, 255, 1),

          4px 4px   0 rgba(0,   0,   0,   .1),

          6px 6px   0 rgba(255, 255, 255, 1),  

          7px 7px   0 rgba(0,   0,   0,   .1);

    box-shadow:

          0 0 2px rgba(0, 0, 0, 0.2),  

          0 1px 1px rgba(0, 0, 0, .2),

          0 3px 0 #fff,

          0 4px 0 rgba(0, 0, 0, .2),

          0 6px 0 #fff,  

          0 7px 0 rgba(0, 0, 0, .2);

	}

	#login:before

	{

    content: '';

    position: absolute;

    z-index: -1;

    border: 1px dashed #ccc;

    top: 5px;

    bottom: 5px;

    left: 5px;

    right: 5px;

    -moz-box-shadow: 0 0 0 1px #fff;

    -webkit-box-shadow: 0 0 0 1px #fff;

    box-shadow: 0 0 0 1px #fff;

	}

	fieldset

	{

    border: 0;

    padding: 0;

    margin: 0;

	}

	#inputs input

	{

    background: #f9f9f9 url(../images/login-sprite.png) no-repeat;

    padding: 15px 15px 15px 30px;

    margin: 0 0 10px 0;

    width: 353px; /* 353 + 2 + 45 = 400 */

    border: 1px solid #ccc;

    -moz-border-radius: 5px;

    -webkit-border-radius: 5px;

    border-radius: 5px;

    -moz-box-shadow: 0 1px 1px #ccc inset, 0 1px 0 #fff;

    -webkit-box-shadow: 0 1px 1px #ccc inset, 0 1px 0 #fff;

    box-shadow: 0 1px 1px #ccc inset, 0 1px 0 #fff;

	}

	#username{  background-position: 5px -2px !important;}

	#password{  background-position: 5px -52px !important;}

	#inputs input:focus

	{

    background-color: #fff;

    border-color: #e8c291;

    outline: none;

    -moz-box-shadow: 0 0 0 1px #e8c291 inset;

    -webkit-box-shadow: 0 0 0 1px #e8c291 inset;

    box-shadow: 0 0 0 1px #e8c291 inset;

	}

	#actions{ margin: 25px 0 0 0;}

	#submit

	{		

    background-color: #ffb94b;

    background-image: -webkit-gradient(linear, left top, left bottom, from(#fddb6f), to(#ffb94b));

    background-image: -webkit-linear-gradient(top, #fddb6f, #ffb94b);

    background-image: -moz-linear-gradient(top, #fddb6f, #ffb94b);

    background-image: -ms-linear-gradient(top, #fddb6f, #ffb94b);

    background-image: -o-linear-gradient(top, #fddb6f, #ffb94b);

    background-image: linear-gradient(top, #fddb6f, #ffb94b);

    -moz-border-radius: 3px;

    -webkit-border-radius: 3px;

    border-radius: 3px;

    text-shadow: 0 1px 0 rgba(255,255,255,0.5);

     -moz-box-shadow: 0 0 1px rgba(0, 0, 0, 0.3), 0 1px 0 rgba(255, 255, 255, 0.3) inset;

     -webkit-box-shadow: 0 0 1px rgba(0, 0, 0, 0.3), 0 1px 0 rgba(255, 255, 255, 0.3) inset;

     box-shadow: 0 0 1px rgba(0, 0, 0, 0.3), 0 1px 0 rgba(255, 255, 255, 0.3) inset;    

    border-width: 1px;

    border-style: solid;

    border-color: #d69e31 #e3a037 #d5982d #e3a037;

    float: left;

    height: 35px;

    padding: 0;

    width: 120px;

    cursor: pointer;

    font: bold 15px Arial, Helvetica;

    color: #8f5a0a;

	}

	#submit:hover,#submit:focus

	{		

    background-color: #fddb6f;

    background-image: -webkit-gradient(linear, left top, left bottom, from(#ffb94b), to(#fddb6f));

    background-image: -webkit-linear-gradient(top, #ffb94b, #fddb6f);

    background-image: -moz-linear-gradient(top, #ffb94b, #fddb6f);

    background-image: -ms-linear-gradient(top, #ffb94b, #fddb6f);

    background-image: -o-linear-gradient(top, #ffb94b, #fddb6f);

    background-image: linear-gradient(top, #ffb94b, #fddb6f);

	}	

	#submit:active

	{		

    outline: none;

     -moz-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.5) inset;

     -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.5) inset;

     box-shadow: 0 1px 4px rgba(0, 0, 0, 0.5) inset;		

	}

	#submit::-moz-focus-inner

	{

  border: none;

	}

	#actions a

	{

    color: #3151A2;    

    float: right;

    line-height: 35px;

    margin-left: 10px;

	}

03. Creazione del file di verifica

A questo punto abbiasmo bisogno di un file che, una volta premuto si “accedi” verifichi se l’utente ha i privilegi o meno di entrare. Per farlo creiamo un file verifica.php e mettiamo al suo interno questo codice:

<?php
session_start(); //inizio la sessione
//includo i file necessari a collegarmi al db con relativo script di accesso
include("connessione_db.php");
include("config.php"); 

//mi collego
mysql_select_db("$db_name",$connessione); 

//variabili POST con anti sql Injection
$username=mysql_real_escape_string($_POST['username']); //faccio l'escape dei caratteri dannosi
$password=mysql_real_escape_string(sha1($_POST['password'])); //sha1 cifra la password anche qui in questo modo corrisponde con quella del db

 $query = "SELECT * FROM login WHERE username = '$username' AND password = '$password' ";
 $ris = mysql_query($query, $connessione) or die (mysql_error());
 $riga=mysql_fetch_array($ris);  

/*Prelevo l'identificativo dell'utente */
$cod=$riga['username'];

/* Effettuo il controllo */
if ($cod == NULL) $trovato = 0 ;
else $trovato = 1;  

/* Username e password corrette */
if($trovato === 1) {

 /*Registro la sessione*/
  session_register('autorizzato');

  $_SESSION["autorizzato"] = 1;

  /*Registro il codice dell'utente*/
  $_SESSION['cod'] = $cod;

 /*Redirect alla pagina riservata*/
   echo '<script language=javascript>document.location.href="privato.php"</script>'; 

} else {

/*Username e password errati, redirect alla pagina di login*/
 echo '<script language=javascript>document.location.href="index.php"</script>';

}
?>

Il funzionamento generale, per chi mastica un minimo di php è abbastanza semplice, si esegue il loop sulla tabella “utenti”  e si verifica che  il nome e la password inserita sia uguale a uno dei dati inseriti in tabella. Se viene trovata una corrispondenza il file reindirizza a privato.php, altrimenti riporta il ciclo al form di accesso iniziale perchè non si possiedono i privilegi necessari.

TIPS: Se volete fare apparire un messaggio in caso di mancato login potete scrivere il link usando un testo via GET che andrà poi recuperato nell’index principale.

es. index.php?&messaggio=Non-puoi-entrare

Usando un semplice if nell’index contenente il login form potete facilmente reperire il messaggio via GET: ecco lo schema:

if GET–>messaggio —> echo”messaggio”

04. Proteggere la pagina privata da accesso diretto

Ma come faccio a proteggere la pagina privato.php nel caso qualche male intenzionato la carichi direttamente (cosa difficile dato che potremmo usare qualsiasi nome, ma pur sempre plausibile).?

Per fare questo controllo ci viene in contro la variabile di sessione “cod” aperta nel corso della verifica durante l’accesso. La sessione indica che l’utente che vuole visualizzare quella pagina HA IL DIRITTO di visualizzarla in quanto si è loggato con successo in precedenza.

Detto questo possiamo verificare e proteggere la pagina da caricamento diretto in questo modo:

<?php
session_start();
//se non c'è la sessione registrata
if (!session_is_registered('autorizzato')) {
  echo "<h1>Area riservata, accesso negato.</h1>";
  echo "Per effettuare il login clicca <a href='index.php'><font color='blue'>qui</font></a>";
  die;
}

//Altrimenti Prelevo il codice identificatico dell'utente loggato
session_start();
$cod = $_SESSION['cod']; //id cod recuperato nel file di verifica
?>

Easy! Basterà inserire queste poche righe di codice all’inizio di ogni pagina per rendere la pagina inviolabile da un eventuale accesso diretto.

05. Funzione di  LogOut con messaggio

Creiamo un file logout.php e mettiamo al suo interno questo codice:

<?php
session_start();
$_SESSION = array();
session_destroy(); //distruggo tutte le sessioni

//creo una varibiale con un messaggio
$msg = "Informazioni: log-out effettuato con successo.";

//la codifico via urlencode informazioni-logout-effettuato-con-successo
$msg = urlencode($msg); // invio il messaggio via get

//ritorno a index.php usando GET posso recuperare e stampare a schermo il messaggio di avvenuto logout
header("location: index.php?msg=$msg");
exit();
?>

Per richiamare lo script vi basterà creare un link “logout” al click dell’utente sarà disconnesso!

Nota: è obbligatorio lasciare session_start() davanti al codice.

Nota2: Assicuratevi di non lasciare righe vuote prima di queste righe di codice (la funzione header a volte da problemi).

06. Sicurezza & co.

Alcune noti importanti sulla sicurezza che dovreste sapere se volete diventare degli sviluppatori:

A) Sql injection: E’ una tecnica hacker che usa alcuni caratteri speciali per “aprire” il codice e rendere controlli mysql inutili, scardinando pertanto il sistema di login. Per testare il vostro login provate a scrivere:

Username: admin ‘ or 1=’1 /*

Password: pippo

Se non avete fatto escape dei caratteri (mysql_real_escape_string) eliminando l’apostrofo il sistema rendere illeggibile la seconda parte della query mysql facendo entrare chiunque e con qualsiasi password.

Come faccio a difendermi? lo script che leggete in questo articolo usa la tecnica mysql_real_escape_string per risolvere questo problema.

B) Brute Force: E’ una tecnica hacker che cerca la possibile  password per accedere al sistema sfruttando alcuni algoritmi di ricerca. Nel nostro sistema  abbiamo ovviato al problema usando la crittografia sha1. Se volete esiste un altro sistema chiamato md5, provatelo!

C) Differenza POST/GET : questa differenza è molto importante e i primi tempi è possibile cadere in errori, più o meno gravi. Ricordate che i dati che passate via GET sono VISIBILI e pertanto intercettabili. Il metodo POST è la scelta obbligata per dati sensibili e passare dati in modo sicuro.

D) Accesso diretto: se la sessione non viene verificata in tutte le pagine, alcuni dati potrebbero essere visti in chiaro sempre a patto che il maleintenzionato sappia il nome della pagina da aprire (caso remoto, ma possibile). Per difendervi vedi il punto 4 della guida.

07. Conclusioni

Bene se siete arrivati a questo ultimo capitolo avrete con tutta probabilità creato il vostro primo sistema di login utente sicuro, veloce e flessibile. Non vi fermate qui però, continuate  a tenervi aggiornati sulle ultime tecniche di sicurezza per essere sempre un passo avanti rispetto ai vostri rivali. 

Nel prossimo articolo dedicato al mondo del php e del developing tratterò un approccio “multi-livello” del sistema di login, molto scalabile e “diverso dal solito” . rimanete connessi su Targetweb.it e condividete la conoscenza su twitter o facebook…potrebbe aiutare altri che come voi vogliono imparare!

[button link=”http://www.red-team-design.com/slick-login-form-with-html5-css3″ color=”blue” size=”small” target=”blank”]Grafica Form Credits[/button]

0 0 voti
Valutazione dell'articolo
Iscriviti
Notificami
guest

Questo sito utilizza Akismet per ridurre lo spam. Scopri come vengono elaborati i dati derivati dai commenti.

133 Commenti
Vecchi
Più recenti Le più votate
Giacomo
Giacomo
14 anni fa

bell’articolo! 🙂
però uffa 🙁 mi rubi le idee xD

Ostap
Ostap
14 anni fa

Non e proprio sicuro 🙂

Anche $_SESSION può essere modificata dall’utente.
Session hijacking

Ostap
Ostap
Rispondi a  Riccardo Mel
14 anni fa

Alla sessione deve essere assegnato un “id unico”

e non il nome utente (cod) e un autorizzato (1) e facilmente sgamabile

Per quando riguarda le password in hash, puoi utilizzare tecnica simile a WP
http://goo.gl/UGriR

oly1982
oly1982
14 anni fa

Gli hash come md5 sha1 non servono per proteggersi dai brute force.
Questi eseguono tentativi ripetuti e se si utilizza una password semplice o classica (come da esempio “prova”) fra i tentativi effettuati verrà scovata in breve tempo.

Gli hash vengono impiegati per due motivi:
– deontologico: nemmeno l’amministratore del sito/database deve poter conoscere le password dei propri utenti (infatti vi è l’abitudine ad utilizzare sempre la stessa su diversi servizi web).
– sicurezza: in caso di sql injection il malintenzionato, in caso di password in chiaro, verrebbe in possesso delle password di tutti i nostri utenti.

Marco Grazia
Marco Grazia
Rispondi a  oly1982
13 anni fa

Sì e no, a parte che nessuno con la testa sulle spalle si metterebbe a realizzare un attacco a forza bruta con il form di un sito, si farebbe sgamare nel giro di un’ora o due e in quel tempo non avrebbe risolto nulla a meno di una botta di culo paurosa.
Questo perché se ragioni un attimo e pensi al tempo di latenza di un server capisci da solo che potresti metterci anche una vita a trovare la giusta password, inoltre basterebbe un controllo sul consumo di banda per capire che dal tuo ip c’è uno strano picco, senza contare che ogni richiesta al server è monitorata e basterebbe controllare un file di log per capire che lì c’è qualche cosa di strano.
Insomma queste cose lasciamole fare dentro i telefilm, un file si cracca dopo averlo copiato dal database in locale (vedi i recenti furti di identità di Microsoft Skype).
Detto questo quello a cui devi stare attento sono le injection, come detto poco fa, il DB lo scarico dopo un’injection che mi da la possibilità di vederlo, come detto su admin 1=1 è la più usata e basta per rovinare la digestione. Dopo tranquillamente mentre giochi con la Play station ti cracchi le password 😀
Quindi conviene controllare principalmente il portone e per farlo mysql_reale_escape_string non serve a molto, anzi quasi a nulla, meglio usare prima i buoni vecchi metodi come htmlentities, adslashes.
Per esempio in questo link (è pubblico tranquilli) ci sono molte tecniche note di sql injection (link in inglese).
Quindi la migliore tecnica è quella di decidere prima cosa proteggere, se non è la banca sotto casa è inutile affannarsi troppo, in ogni caso non essere mai banali: non permettere di registrare un account con caratteri speciali, vanno bene solo lettere, numeri ed eventualmente spazi, mai segni di interpunzione, poi li si controlla in fase di inserimento, non devono esserci segni di = (così 1=1 non si potrà usare 😉 non usare md5 perché oramai corrotto, usare sha1, a noi non ci cambia nulla tranne scrivere 4 caratteri in luogo di tre 🙂 ma la sicurezza aumenta.
Fare un vero escaping delle stringhe, magari usando i filtri in luogo di altre funzioni, comunque molto sicure; usare funzioni che permettono il binding delle variabili, in altre parole usare mysqli (improved) in luogo di mysql (anche perché PHP lo sta eliminando del tutto), usare i permessi degli accessi al database, per impedire che chi si logga può fare di tutto, come ad esempio cancellare l’intero database.
Usare le sessioni non mettendoci valori banali come 1 🙂 meglio un token realizzato con sha1(nome utente + uniqid) dove uniqid è registrato nel database accanto a nome utente e password e formato in automatico al momento della registrazione.
Quindi $_SESSION[‘log’] = sha1($nome_utente + $uniqid); poi si verifica sempre se esiste (isset) e se non è vuoto (empty) e quindi se il valore interno è giusto (cosa complicata perché ci costringe a verificare nel database ogni volta).
Basta? No ma è già tanto.

Ciauz M.

Elisa
Elisa
Rispondi a  Marco Grazia
13 anni fa

Ho trovato diversi spunti interessanti nel tuo articolo, Riccardo..grazie.
Mi interessava, però, avere anche dei chiarimenti da parte di Marco Grazia o da parte tua riguardo il suo commento postato il 20.11.12 12:54.
Lì dove dice:

Come si fa nel concreto a verificare se “il valore interno è giusto” partendo da $_SESSION[‘log’]?
esempio: 55088f461b92f36025f6e13a3f41203b861b631c
Grazie.

Marco Grazia
Marco Grazia
Rispondi a  Elisa
8 anni fa

Mamma mia, nemmeno ricordavo di aver postato in questa pagina, e tornarvi dopo anni credo sia quanto meno inutile; spero infatti che i tuoi dubbi tu li abbia oramai risolti.

Ciao.

Giacomo
Giacomo
14 anni fa

Io di solito quando faccio sistemi di login associo ad ogni utente un codice generato casualmente tramite un array e salvo nel cookie o nella sessione quel valore.
è un metodo abbastanza sicuro visto che anche se il cookie o la sessione possono essere modificare a meno che non hai un c*** assurdo la vedo dura trovare il codice di un altro utente

Marco Grazia
Marco Grazia
Rispondi a  Giacomo
13 anni fa

A be ma non bisogna mica scoprire il valore del cookie, anche perché è un’impresa titanica oltre che inutile, basta copiarlo 😉

Ciauz M.

Alessandro
Alessandro
14 anni fa

Ottimo articolo soprattutto per gli spunti di tutti gli sviluppatori.
Personalmente trovo che combinare la tecnica delle password in hash con un codice alternativo generato in maniera casuale (come suggerisce Giacomo) anch’esso in hash possa essere un buon compromesso.
Per il resto, che si scelga SESSION o COOKIE entrambe sono modificabili quindi bisogna per forza escogitare qualcosa di “alternativo”.

Enrico Martelli
Enrico Martelli
14 anni fa

Salve, mentre provavo questo codice sul mio sito, mi sono accorto che nel tutorial non c’è il file connessione_db.php, e senza di questo mi da diversi errori (credo, visto che gli errori che mi trova sono appunto l’include mancante e la variabile $connessione che deduco appartenga al file connessione_bd.php).
Volevo chiedere quale fosse il contenuto di questo file mancante. Grazie

Enrico Martelli
Enrico Martelli
Rispondi a  Riccardo Mel
14 anni fa

Grazie mille. Se può servire qui http://wordpress.org/support/topic/php-deprecated-warnings-on-every-screen c’è scritto il motivo dell’errore DEPRECATED, e c’è scritto un semplice rimedio.

Alessandra Frisan
Alessandra Frisan
Rispondi a  Riccardo Mel
6 anni fa

Salve, vorrei sapere qual’è il file connessione_db.php, per favore.
Grazie

Giuseppe
Giuseppe
14 anni fa

Ciao, sto provando il tuo script ma mi da questi errori:
Deprecated: Function session_is_registered() is deprecated in C:\xampp\htdocs\cms\privato.php on line 4

Notice: A session had already been started – ignoring session_start() in C:\xampp\htdocs\cms\privato.php on line 11.

Complimenti per lo script

Giuseppe
Giuseppe
14 anni fa

Ho notato che forse ci sono degli errori nella pagina privato.php
è ripetuto due volte session_start() e poi mi da un problema con !session_is_registered.
Ciao e grazie

Salvatore
Salvatore
14 anni fa

Bell’articolo! Eventualmente, per aumentare ulteriormente la sicurezza, potresti implementare il così detto “password salting”, aggiungendo alla password una stringa alfanumerica bella lunga prima di farne l’hash. In questo modo, nel caso in cui qualcuno riesca con un attacco ad entrare nel database e a rubare la tabella utenti, sarà molto più difficile per lui riuscire a decifrare le password (anche quelle più deboli) non conoscendo la stringa che hai aggiunto. L’ideale è salvare la stringa “salt” in un posto sicuro, ovvero in una cartella non accessibile via web. Framework come cakephp (e non solo) implementano nativamente questo sistema nelle loro classi di autenticazione.

Enrico
Enrico
14 anni fa

ciao,
complimenti per lo script 😉
una domanda banale, come hai fatto a mettere omino e chiavetta nei campi user e password? Fanno la loro figura…
Grazie,
Enrico

Andrea
Andrea
14 anni fa

Ottimo articolo, complimenti!

Piccolo appunto: per le password è meglio non usare MD5, ormai è troppo insicuro. Meglio affidarsi a SHA1 in attesa dello standard di SHA2 😉

Andrea
Andrea
Rispondi a  Riccardo Mel
14 anni fa

Ottimo, lo leggerò sicuramente!! 😉

Un’altra domanda, magari anticipo qualcosa che verrà trattato in questo nuovo articolo. Quando viene eseguita la richiesta POST tra la pagina di login e lo script php i dati passano in chiaro. C’è un modo (sicuro e affidabile) per risolvere questa cosa? O bisogna affidarsi ad https?

Grazie e ancora complimenti!

Aldo
Aldo
14 anni fa

Ciao mi è piaciuto l’articolo, complimenti. Ho però trovato un piccolo errore, non specifichi il database. Per risolverlo dovresti modificare il file di verifica, questa riga:

$query = “SELECT * FROM login WHERE username = ‘$username’ AND password = ‘$password’ “;

dovrebbe diventare:

$query = “SELECT * FROM $db_name.login WHERE username = ‘$username’ AND password = ‘$password’ “;

In questo modo funziona 😀 Ciao e ancora complimenti

Aldo
Aldo
14 anni fa

Scusa hai agione, scusa avevo modificato un po’ lo script e non mi ero accorto che la selezione del database l’avevo tolta. Comunque è giusto anche il mio metodo. Ciao e complimenti ancora!

Giuseppe
Giuseppe
14 anni fa

Ciao complimenti per l’ottimo articolo, sto provando ad implementare lo script per far autenticare gli utenti in alcune pagine secondo livelli di autenticazione ma ho problemi non capisco come fare,,,un aiutinino??
Grazie

Giuseppe
Giuseppe
14 anni fa

Grazieee Riccardo, io ho inserito nel file da proteggere dopo l’inclusione del file privato un if SESSION ed è tutto perfetto.
Posso fare una domanda stupida? Non riesco ad inserire le immagine nel login. Credo che mi manchi il file “login-sprite.png”.
Grazie
Giuseppe

Enea
Enea
14 anni fa

Ciao Riccardo
hai già sfornato la versione 2 di questo già ottimo sistema dia utenticazione?

enea
enea
Rispondi a  Riccardo Mel
14 anni fa

Se la posto qui come beta ti aiuto a testarla.

xeryan
xeryan
14 anni fa

aggiungo questo:
per fare la funzione “ricorda i miei dati” si usano i cookie, dove viene memorizzato ID utente e un token, si dovrebbe controllare sempre che l’utente corrisponda all’ID nella sessione, perchè i cookie si possono facilemente modificare.. le sessioni invece è molto più difficile, oserei dire impossibile ma non voglio sbagliarmi

xeryan
xeryan
14 anni fa

ma anche no ^^ scusate mi sono sbagliato, basta controllare in ogni pagina che il token corrisponda effettivamente all’utente associato nei cookie, questo dovrebbe bastare

Luca
Luca
14 anni fa

Ciao sarei interessato a un cms per annunci vetrina quanto mi costerebbe?il mio contatto skype e leo-lleon contattatemi

Edoardo
Edoardo
14 anni fa

Il database alla creazione delle tabelle segnala errore

Matteo Mosconi
Matteo Mosconi
14 anni fa

Onestamente trovo il login molto simile a quello di Red Team Design
Oltre che ribadire che è importante salvare solo gli hash delle password ti consiglio di inserire in sessione l’ip dell’utente e confrontare ogni volta che la persona che richiede il file abbia lo stesso ip di quello in sessione, altrimenti la sessione deve essere distrutta. Questo può essere utile per proteggersi ulteriormente dalla manipolazione dei cookie. Cheers

Guido
Guido
14 anni fa

Ciao Riccardo! Complimenti un tutorial molto interessante e ben scritto! Ogni volta che passo da queste parti trovo sempre buoni motivi per ritornarci! 😉

Federico
Federico
14 anni fa

Ciao mi chiedevo se avessi già aggiunto il nuovo articolo con i vari suggerimenti, sono molto curioso di vederlo…

Federico
Federico
14 anni fa

Ciao Riccardo, a quando il nuovo articolo? Sono molto curioso di vederlo.

Rocco
Rocco
13 anni fa

Ciao Riccardo,
sto provando il tuo sistema ma ricevo questo errore:

Notice: A session had already been started – ignoring session_start() in C:\Program Files\Apache Software Foundation\Apache2.2\htdocs\cms\area\privato.php on line 8

Penso sia lo stesso che capitava a Giuseppe.

Grazie in anticipo.

Matteo
Matteo
13 anni fa

Se non sbaglio mysql_real_escape_string() è deprecato…

newbie
newbie
13 anni fa

temo di avere fatto qualche errore perchè le pagine protette mi si aprono quando vi si accede direttamente dopo che è stato fatto almeno un accesso corretto sulla stessa macchina. le session restano sulla macchina indipendentemente dall’avvenuta autorizzazione. significa che se qualcuno prende la postazione di un utente autorizzato accede immediatamente al sito anche senza conoscere username o password. è un errore mio o un bug del programma?

Matteo
Matteo
Rispondi a  newbie
13 anni fa

Non e’ un problema, funziona cosi su tutti i siti twitter e facebook compresi. La sessione rimane aperta finché non chiudi il browser.

newbie
newbie
13 anni fa

grazie per l’aiuto ma anche chiudendo il browser la sessione è sempre lì….

newbie
newbie
13 anni fa

ringrazio ancora per l’attenzione che mi dai. in realtà non ho copiato tutto esattamente per ragioni diverse (avevo già fatto una parte di autenticazione molto simile e l’ho adattata) ma la filosofia è la stessa. il problema mi nasce dal fatto che le session restano comunque sulla macchina anche dopo avere chiuso il browser e me le ritrovo pure successivamente quindi.
inoltre non riesco a distinguere quando sto facendo il primo accesso alla prima pagina da quando vi sto ritornando dopo essermi già autenticato. per questo probabilmente mi resta la session sempre viva.
aggiungo che,prevedendo che si possa uscire senza logout, non ho implementato una gestione specifica il che rende il mio codice parzialmente diverso ma non nella sua filosofia. è possibile che un utente cambi semplicemente sito senza fare logout. spero di essere stato chiaro

newbie
newbie
13 anni fa

come si comporta il programma nel vostro caso se, dopo essere stati validati, per qualunque motivo si torna alla prima pagina (quella con i $_POST). come si fa a controllare la correttezza della password se i $:POST per username e password non sono più settati?

più semplicemente: como distinguere il caso di un primo accesso (in cui bisogna impostare SESSION) con quello in cui, dopo essere stato ammesso al sito, voglio ritornare sulla pagina al punto n.3?

ps: a me risulta che registrare le sessione sia deprecato

Clear
Clear
13 anni fa

Ma se io volessi richiamare l’username o qualsiasi dato utente di chi si è loggato dopo che la sessione è iniziata?

Ad esempio, io mi loggo, e poi vado su una pagina dove vedo stampato il mio nome, la password e tutto quello che voglio.. Come faccio?

Giacomo
Giacomo
13 anni fa

Ciao Riccardo,
Stavo provando ad utilizzare la tua pagina di login con verifica intanto per fare un po di pratica, ma riscontro un problema quando vado ad effettuare il login, cioè al posto di indirizzarmi su una pagina come hai scritto tu privato.php mi indirizza direttamente in index.php come se user e password siano sempre sbagliate anche se sono ‘prova’ ‘prova’
come posso fare? grazie

Antonio
Antonio
13 anni fa

Ciao Riccardo, ho creato il database e nella SQL ho aggiunto il codice che hai dato all’inizio dell’articolo.
Purtroppo mi segna quest’ errore:

#1064 – You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ‘INSERT INTO `login` ( `id` , `username` , `password` ) VALUES ( NULL , ‘utente’,’ at line 8

Sai qual è il problema?

Andrea
Andrea
Rispondi a  Antonio
13 anni fa

Se applichi prima il codice per creare la tabella senza “insert” e poi, dopo aver fisicamente creato la tabella lanci la parte si sql per popolarla l’errore scompare .. HTH

Enrico
Enrico
13 anni fa

Carissimo Riccardo,
Sto scrivendo una autenticazione utenti per un sito e prendo volentieri spunto dalla tua, anche se farò qualche mio intervento al fine di aumentare la sicurezza.
Mi piacciono le iconcine login-sprite.png , riesci ad inviarmele ? Ti ringrazio per l’attenzione

Marco Grazia
Marco Grazia
13 anni fa

In un punto dell’articolo si dice che header non sono sempre affidabili, in realtà sono perfetti solo bisogna stare attenti al loro uso.
Un modo per non curarsi degli spazi eventualmente inseriti prima del loro uso è quello di far processare la pagina ad un pre processore, parolona per dire che basta inserire in alto, subito dopo l’intestazione di script a quel punto si possono usare impunemente gli header che risultano molto comodi non solo per passare parametri vari, ma anche per evitare di usare il javascript per effettuare una redirezione.

Ciauz M.

marco
marco
13 anni fa

Ciao, intanto grazie per il tutorial!! mi serve un aiuto! riporto il tipo di errore riscontrato quando carico la query:
Errore
query SQL:
CREATE TABLE `login` (
`id` INT( 11 ) NOT NULL AUTO_INCREMENT ,
`username` VARCHAR( 64 ) NOT NULL ,
`password` VARCHAR( 64 ) NOT NULL ,
PRIMARY KEY ( `id` )
) ENGINE = MYISAM INSERT INTO `login` ( `id` , `username` , `password` )
VALUES (
NULL ‘utente’, sha1( ‘prova’ )
)

Messaggio di MySQL: Documentazione
#1064 – You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ‘INSERT INTO `login` (`id` ,`username` ,`password`)
VALUES (NULL ‘utente’, sha1′ at line 3

Che significa???? qualcuno mi puo’ aiutare?

Wally
Wally
Rispondi a  marco
11 anni fa

In sql ti da errore perche’ dovresti mettere:

CREATE TABLE `login` (
`id` INT( 11 ) NOT NULL AUTO_INCREMENT ,
`username` VARCHAR( 64 ) NOT NULL ,
`password` VARCHAR( 64 ) NOT NULL ,
PRIMARY KEY ( `id` )
) ENGINE = MYISAM

Fare “esegui” e poi mettere :

INSERT INTO `login` ( `id` , `username` , `password` )
VALUES (
NULL ‘utente’, sha1( ‘prova’ )
)

Ciauuuu 😉 by Wally

Marco Grazia
Marco Grazia
13 anni fa

Devi elimanre NULL.
Oltre tutto se scrivi ( `id` INT( 11 ) NOT NULL AUTO_INCREMENT , ) cioè NOT NULL perché gli dai come valore proprio NULL?
Nel caso poi di valori autoincrementanti come questo caso, non metterci nessun valore, proprio nulla, cioè finisci la query con … VALUES ( ‘utente’, sha1( ‘prova’ ) )

CiauZ M.

Guido
Guido
13 anni fa

Ciao, ho trovato molto utile il tuo post, ma ho un problemino: non capisco perchè non mi riconosce le variabili; per provare a vedere dove fosse il problema ho provato a sostituire le variabili come $host e $db_user con i relativi valori. Inoltre questo problema si ripete nel file verifica.php dove non mi legge $username e $password, ma se inserisco i valori che ho nel db funziona tutto.
Spero tu mi possa aiutare, grazie.
Guido

Sem
Sem
13 anni fa

Ciao. Perfetto il post.
Ma vorrei integrare una piccola funzione.
Nel DB ho associato all’utente A la paginariservataA.php.
Come posso fare a recuperarla ed inserire nel location?
Grazie mille.
Sem

giacomo
giacomo
13 anni fa

Ciao, complimenti per le guide, sono chiare e facili da seguire.
Io mi sono avvicinato da pochissimo (settimane) al php. ho sviluppato una piccola app dinamica in php, ora prima di pubblicarla online vorrei inserire una pagina per il login, l’applicazione non avrà bisogno di più utenti, ma sarà monoutente.
Ho seguito la tua guida però sono bloccato alla pagina verifica.php, nel senso che quando inserisco user e pwd il browser rimane impuntato su verifica.php e non va alla pagina privato.php.
Perchè?

giacomo
giacomo
13 anni fa

Dopo due ore posso rispondermi da solo, Le funzioni “session_register” e “session_is_registered” sono deprecate da php 5.4 , al loro posto usare ” $_SESSION[‘autorizzato] ” e ” if(isset($_SESSION[‘autorizzato’]))
{ print(“la sessione è autorizzato”); } .
Vi rimando al manuale per ulteriori dettagli http://php.net/manual/it/function.session-is-registered.php

marco
marco
Rispondi a  giacomo
13 anni fa

Se non ho capito male quello che dici te il codice dovrebbe diventare nel file verifica.php
/*Registro la sessione*/
$_SESSION[‘autorizzato’];
$_SESSION[“autorizzato”] = 1;
E nell’altro file
<?php
session_start();
//se non c'è la sessione registrata
if(isset($_SESSION['autorizzato'])) {
echo "Area riservata, accesso negato.”;
echo “Per effettuare il login clicca qui“;
die;
}

//Altrimenti Prelevo il codice identificatico dell’utente loggato
session_start();
$cod = $_SESSION[‘cod’]; //id cod recuperato nel file di verifica
?>
Pero’ ora ogni volta che faccio il login mi dice che non posso accedere mi puoi aiutare?

Federico
Federico
13 anni fa

Buongiorno,

a me da qualche errore il file verifica.php alla linea 8 e 15

vi posto gli errori se possono essere utili:

( ! ) Notice: Undefined variable: connessione in C:\www\test\verifica.php on line 8
Call Stack
# Time Memory Function Location
1 0.0007 255408 {main}( ) ..\verifica.php:0

( ! ) Warning: mysql_select_db() expects parameter 2 to be resource, null given in C:\www\test\verifica.php on line 8
Call Stack
# Time Memory Function Location
1 0.0007 255408 {main}( ) ..\verifica.php:0
2 0.0022 259712 mysql_select_db ( ) ..\verifica.php:8

( ! ) Notice: Undefined variable: connessione in C:\www\test\verifica.php on line 15
Call Stack
# Time Memory Function Location
1 0.0007 255408 {main}( ) ..\verifica.php:0

( ! ) Warning: mysql_query() expects parameter 2 to be resource, null given in C:\www\test\verifica.php on line 15
Call Stack
# Time Memory Function Location
1 0.0007 255408 {main}( ) ..\verifica.php:0
2 1.0281 267296 mysql_query ( ) ..\verifica.php:15

il mio di si chiama my_snook
ho cercato di fare le dovute modifiche ma non sono molto esperto di php

grazie in anticipo

Federico

luigi
luigi
13 anni fa

ciao riccardo, visto che sono un principiante in materia, cioè in pratica questo script serve per creare un pannello di controllo per amministrare un sito web o sbaglio

marco
marco
13 anni fa

Qualcuno mi puo’ aiutare non riesco a creare la sessione anche se inserisco username e password correttamente mi fa arrivare nella pagina sicura ma mi da la frase per chi non ha l’autorizzazione ad accedere, mio contatto skype kintaro164

Andrew
Andrew
13 anni fa

Ciao! scusa ma a me la pagina non si presenta come nella foto, nello stile c’è il percorso dell’immagine che però noi non abbiamo comunque , sai come posso far apparire la pagina come in immagine?
Un’altra domanda per aggiungere l’omino sulla text box, quali sono le righe del codice?

Andrea
Andrea
13 anni fa

Ciao! A me la pagina non appare come dovrebbe nel senso che non compaiono gli omini, nel css c’è un url dell’immagine che noi non abbiamo, è per quello? sai come posso risolvere?

marco
marco
13 anni fa

ciao! ottimo articolo, potresti chiarirmi una cosa? nel file verifica.php c’è questo pezzo:


/*Redirect alla pagina riservata*/
echo 'document.location.href="privato.php"';

} else {

/*Username e password errati, redirect alla pagina di login*/
echo 'document.location.href="index.php"';

}

dove se il login è sbagliato và in index.php mentre se è giusto và in privato.php (la pagina da proteggere), e se io invece volessi rendere questa protezione per qualsiasi pagina che voglio proteggere cosa dovrei mettere al posto del redirect alla pagina privato.php?

mi spiego meglio, ad esempio voglio andare nella pagina pippo.php , che ho protetto con questo codice come hai detto tu:

clicco sul link a pippo.php e giustamente mi chiede nome utente e password, io vorrei che mettendo le credenziali mi aprisse la pagina pippo.php, come dovrei fare per far funzionare la cosa? grazie in anticipo ciao!

Filippo
Filippo
13 anni fa

Complimenti! Utilissimo!!!

Nicola
Nicola
13 anni fa

Ciao Riccardo,
parto con il complimentarmi per l’ottimo articolo.
Ho una piccola richiesta…
Non è che sarebbe possibile mettere a disposizione direttamente un piccolo archivio ZIP/RAR o altro contentente TUTTI i file richiesti per il corretto funzionamento dello script?
Secondo me sarebbe molto comodo.

PS: A me per qualche motivo si pianta al caricamento del file “verifica.php” e rimane una pagina completamente bianca nel browser… 🙁

leopardinoz
leopardinoz
13 anni fa

ciao Riccardo! bellissimo articolo complimenti!
ho iniziato solo ieri con php ma ce la devo fare o almeno ci provo! anche se la vedo molto dura visto che o troppe cose per la testa e mi incasino spesso 🙂 ma provare non costa nulla infondo anche perchè dal 2001 sto spendendo una valanga di soldi x 2 siti e mi mancavano proprio un paio di cose utili tipo autenticazione e db che nn aveevo mai fatto 🙂 speriamo bene se vuoi aggiungimi skype leopardinoz (faccia di un gatto nero) stessa con cui ho fb e tii ho fatto poco fa il mi piace della pagina 🙂 almeno se ho qualche problemino e hai tempo spero che mi potrai aiutare ciau Marck

Rimani Aggiornato
Nuove idee, zero Spam
Ti invieremo solo le ultime novità di articoli o nostri progetti.
Iscrivendoti accetti la nostra privacy poliicy. Una volta iscritto, ricordati di attivare l'iscrizione cliccando sul link ricevuto via mail.
133
0
Esprimete la vostra opinione commentando.x