- Home
- Categorie
- Coding e Sistemistica
- MYSQL e altri Database
- [Tutorial] La Gestione degli utenti in PHP e MySQL
-
in un caso studio si cerca di trovare assieme la soluzione migliore rimanendo in bilico tra la funzionalità del progetto e gli esempi "a scopo didattico".
la relazione uno a uno tra due tabelle, personalmente, viene usata quando mi trovo a dover interrogare una tabella da più di 20 campi (numero indicativo) dove i campi che effettivamente mi interessano sono pochissimi (2 o 3) ed il numero di record è potenzialmente elevato.
Per dare un esempio concreto su cui ragionare senza inventarsi un progetto ad hoc per spiegare il concetto, l'anagrafica utenti calza a pennello.
Se l'anagrafica utenti avesse tutti i campi necessari per memorizzare vita morte e miracoli degli utenti (indirizzi, vari numeri di telefono, vari siti email e chi più ne ha più ne metta) e si raggiunge una dimensione di 30-40 campi per fare semplicemente il login non voglio far girare un tabellone così grande ed in questo caso separo le due tabelle in una striminzita che quindi sarà snella e veloce e l'altra (più grossa e lenta) che verrà interrogata solo quando saranno effettivamente necessarie tutte le info.
pro e contro:
pro:
una maggiore velocità di esecuzione quando faccio il login perchè devo interrogare una tabellina di pochi campi e ben indicizzata (gli indici li vedremo quando analiziamo come fare le tabelle nel dettaglio).contro:
una lentezza leggermente maggiore quando il motore deve estrarre i dati completi del singolo utente in quanto dovrà risolvere un join.l'interrogazione nel primo caso sarà:
select * from utenti where (condizioni)nel secondo sarà:
select (dati che mi interessano) from utenti, utenti_info_aggiuntive where utenti.id = utenti_info_aggiuntive.id_utente where (condizioni)pareri?
-
@Tymba said:
pareri?
Sì. Che oltre al motivo indicato da te, la soluzione multi-tabella è generalmente indicata per progetti destinati a possibili ampliamenti.
Se un sito possiede forum, blog e sondaggi e tutti e tre questi servizi beneficiano dell'autenticazione degli utenti, ha senso creare una tabella con le informazioni generiche e valevoli per tutti i servizi (username, password, IP, ecc.) ed una tabella in più per ciascuno dei servizi esistenti, contenente solo le informazioni-utente relative al servizio al quale la tabella è dedicata.
Se un domani sarà necessario aggiungere un guestbook o un modulo per spedirsi messaggi privati, ci si limita a creare una nuova tabella per il nuovo servizio, senza toccare nessuna di quelle già esistenti.
Separare le informazioni relative all'autenticazione da quelle aggiuntive e non essenziali all'autenticazione è sempre una buona idea. Anche perché la tabella con le informazioni per l'autenticazione subisce query continue, anche una ad ogni caricamento di pagina, a seconda dell'implementazione. Meglio che sia piccola, come dicevi tu.
-
@ LowLevel: E' vero che io ho scritto il post, ma il progetto era già stato studiato tra i mods, quindi non seguire solo me, ma anche tutti gli altri mods.
Io ho solo dato una mano su come realizzare il DB, voi potete seguire quella traccia oppure potete modificarla a vostro piacimento.
Preferirei che questo progetto avesse anche finalità didattiche, come se fosse una vera pillola, in quanto sarebbe più facile da comprendere e da modificare o estendere. Quindi non sarebbe male se scriveste un pò di righe in più nel vostro post anche per spiegare cosa state facendo e come lo state facendo.
Per il fatto della password mandata in chiaro, sarebbe una buona cosa se ci spiegassi come fare per mandarla già criptata, perchè ripeto: tutto ciò che può riguardare un sistema di gestioni utenti è meglio inserirlo. E la sicurezza mi sembra rientrare in questi
Non fatevi venire strane idee su come un moderatore vedrà il vostro messaggio: al massimo vi aiuterà a migliorarlo, di certo non vi
-
http://pajhome.org.uk/crypt/md5/
E' usato per convertire in MD5 tramite Javascript
-
Ok, PaTeR, adesso mi è chiaro. Grazie dei chiarimenti.
Espongo quello che farei io per migliorare la sicurezza del sistema di autenticazione. Visto che sono ancora allo stadio progettuale, a mio parere è presto per scrivere codice. Penso che sia il caso di farlo solo dopo aver raggiunto un accordo comune sul sistema da implementare, che può variare a seconda del contributo di tutti gli interessati.
Problema: la password non dovrebbe essere trasmessa in modo tale che un eventuale intercettatore la possa utilizzare per loggarsi.
Considerazioni: è evidente che limitarsi a criptare la password con un algoritmo come md5() e progettare il sistema in modo che il server accetti dal login dell'utente la password criptata con md5() non serve a nulla, perché se il sistema si accontenta della password criptata con md5() allora è sufficiente che l'intercettatore intercetti la password criptata e la invii al server. In poche parole il livello di sicurezza non è stato aumentato di una virgola rispetto all'uso della password in chiaro. [parlare di criptazione con md5() è improprio, ma sorvoliamo per semplicità]
Soluzione: la password inserita dall'utente non va trasmessa in nessun modo. Al contrario, è meglio trasmettere un'informazione (che chiameremo "informazione combinata") che si basa sia sulla password inserita dall'utente sia su un valore/stringa casuale, generato dal server ad ogni login e che solo il server conosce. Il calcolo di questo valore combinato spetta a Javascript e viene effettuato prima di spedire i contenuti del form di login.
Quando l'informazione combinata viene ricevuta dal server, il server controlla se essa è identica a quella che viene fuori combinando la stringa casuale precedentemente generata, che il server deve conoscere, con la password dell'utente, che in teoria dovrebbe essere presente nel database. In altre parole il server fa lo stesso calcolo fatto precedentemente dal Javascript, ma usando la password archiviata invece di quella inserita dall'utente (e che il form non spedisce): se il valore ricevuto e quello calcolato coincidono, allora l'utente ha inserito la giusta password.
Nasce però il problema che, per effettuare il calcolo, il server deve essere a conoscenza della password dell'utente. Ma memorizzare la password in chiaro nell'archivio non è una buona regola. Pertanto si introduce un livello di criptazione in più in modo che l'informazione combinata venga calcolata (sia dal Javascript che dal server) non combinando il valore casuale con la password in chiaro bensì combinando il valore casuale con un md5() della password. Il server quindi si può accontentare di memorizzare in archivio non la password in chiaro ma il suo md5(), ed il problema è risolto.
Sicurezza: se l'intercettatore intercetta l'informazione combinata, non se ne fa nulla. Quando l'intercettatore prova a fare il login, il server creerà infatti un valore casuale diverso rispetto a quello generato in precedenza per l'utente. Il server si aspetta di ricevere un'informazione combinata che si basa sul nuovo valore casuale, ma l'intercettatore ha in mano solo un'informazione combinata generata in base ad un precedente valore causale. Quindi gli è impossibile effettuare il login con quello che ha intercettato.
Implementazione:
-
Al login, il server genera un valore casuale, lo memorizza in una variabile di sessione e lo scrive fisicamente nel codice Javascript contenuto nella pagina, assegnandolo ad una variabile Javascript.
-
Quando l'utente invia il form con i dati, viene chiamata una funzione Javascript che calcola innanzitutto l'md5() della password, e poi l'informazione combinata, ovvero l'md5() del "valore casuale più l'md5() della password".
-
I contenuti del campo della password nel form vengono cancellati e la funzione Javascript assegna l'informazione combinata ad un campo hidden del form.
-
I contenuti del form vengono finalmente inviati al server attraverso il metodo post.
-
L'eventuale intercettatore intercetta il valore combinato, ma non se ne farà nulla.
-
Il server riceve il valore combinato e controlla che sia effettivamente ciò che esce fuori facendo l'md5() del valore casuale (che sta in una variabile di sessione) con l'md5() della password (che sta nel database).
-
Se i valori corrispondono allora l'utente ha inserito la giusta password e il sistema di autenticazione considera l'utente autenticato.
Note informatiche: che cosa diavolo è questo md5()? md5() è un algoritmo che, partendo da una stringa di byte di qualunque lunghezza, genera una stringa di sedici byte che può essere considerata l'impronta digitale (in gergo chiamata hash o fingerprint) della stringa di partenza.
L'md5() non è un algoritmo di criptazione che permette di risalire dall'impronta alla stringa originale, perché ad ogni impronta corrispondono infinite stringhe di partenza. In altre parole, non c'è una corrispondenza uno-ad-uno tra stringa di partenza ed impronta bensì una corrispondenza molti-ad-uno, ovvero stringhe di partenza diverse possono generare impronte identiche.
Nonostante questa limitazione, dovuta al semplice fatto che le combinazioni in sedici byte sono tante ma pur sempre finite, l'algoritmo è stato progettato in modo tale che variazioni minime nella stringa di partenza generino variazioni gigantesche nelle impronte corrispondenti. Quindi non c'è pericolo che l'md5() della password "pippo" sia simile a quello della password "peppo": le impronte delle due stringhe saranno completamente diverse.
Questo implica che, pur progettando un sistema di autenticazione che archivia non le password ma le impronte md5() delle password, è estremamente improbabile che qualcuno becchi una password che generi lo stesso valore md5() della vera password dell'utente.
-
-
Davvero Ottimo
Ora non resta che l'implementazione in JS...
-
Codice HTML del form di login:
<form name="login" method="post" action="<? echo $_SERVER['PHP_SELF']; ?>" onsubmit="encrypt();"> Nome utente: <input type="text" name="username"> Parola di accesso: <input type="password" name="pw"> <input type="hidden" name="md5ed" value=""> <input type="hidden" name="login" value="1"> <input type="submit" value="Accedi"> </form>
Codice Javascript:
<script type="text/javascript" src="md5.js"></script> <script type="text/javascript"> <!-- function encrypt () { <? echo "var challengeword = '" . $_SESSION['challengeword'] . "' ;" ; ?> var pw = document.login.pw.value ; if (pw) { pw = md5 (pw) ; pw = md5 (pw + challengeword) ; document.login.pw.value = '' ; document.login.md5ed.value = pw ; } } // --> </script>
La variabile di sessione challengeword è il valore casuale con cui la password inserita dall'utente viene combinato.
Può essere generata scrivendo in cima alla pagina un po' di codice PHP, del tipo:
$_SESSION['challengeword'] = md5 (mt_rand ());
Ovviamente la sessione deve essere già attiva.
Chi scrive il codice PHP per il controllo del login? Sempre io?
-
Vediamo qualche altro partecipante...
-
i miei complimenti
veramente uno spunto OTTIMO su cui ragionare.
ho letto con molta attenzione quanto scritto ed ora devo metabolizzare
-
@Tymba said:
i miei complimenti
veramente uno spunto OTTIMO su cui ragionare.
ho letto con molta attenzione quanto scritto ed ora devo metabolizzare :)non sei l'unico, appena imparato da lowlevel ho aggiornato il mio sistema di log
-
l' idea di LowLevel è di una praticità ed efficacia disarmanti, non è che mi trovi spesso a gestire l'autenticazione degli utenti, comunque non avevo mai pensato ad usare un metodo simile, quindi intanto subito un bel grazie .
Adesso mi guardo bene bene il codice e preparo una mia versione del controllo login in PHP.
-
@emmebar said:
l' idea di LowLevel è di una praticità ed efficacia disarmanti, non è che mi trovi spesso a gestire l'autenticazione degli utenti, comunque non avevo mai pensato ad usare un metodo simile, quindi intanto subito un bel grazie .
Adesso mi guardo bene bene il codice e preparo una mia versione del controllo login in PHP.Poi magari cerca di integralrla qui, così vediamo di curare un'altro aspetto del progetto
-
Fino a ieri il mio bizzarro sistema di autenticazione faceva in modo che le password fossero memorizzate nell' id_sessione in chiaro. Ho risolto (adesso non lo sono più).
Adesso però devo trovare il modo per non trasmettere più la password utente nel form di login ma bensì quell'informazione combinata di cui si è parlato.
L'informazione combinata deve tenere conto di due fattori:
stringa casuale che solo il server conosce;
password inserita nel formPosso creare una funzione personalizzata (stringa/password) per generare l'informazione combinata? Se ho capito bene la risposta è SI.
Deve essere obbligatoriamente in javascript la funzione? La risposta è NO se ho capito.
-
@linus said:
Fino a ieri il mio bizzarro sistema di autenticazione faceva in modo che le password fossero memorizzate nell' id_sessione in chiaro. Ho risolto (adesso non lo sono più).
Adesso però devo trovare il modo per non trasmettere più la password utente nel form di login ma bensì quell'informazione combinata di cui si è parlato.
L'informazione combinata deve tenere conto di due fattori:
stringa casuale che solo il server conosce;
password inserita nel formPosso creare una funzione personalizzata (stringa/password) per generare l'informazione combinata? Se ho capito bene la risposta è SI.
Deve essere obbligatoriamente in javascript la funzione? La risposta è NO se ho capito.Si, il java script si
-
@PaTeR said:
Poi magari cerca di integralrla qui, così vediamo di curare un'altro aspetto del progetto
E' esattamante quello che voglio fare .
-
come stiamo procedendo? :
-
@Tuonorosso said:
come stiamo procedendo? : 8)Cerchiamo nuovi utenti che possono partecipare!!!
-
ok
intanto non ci conviene dividerci i compiti noi che già ci siamo?
-
@Tuonorosso said:
come stiamo procedendo? :
Per il controllo sono un po' indietro, ho avuto una montagna di cose da fare in questi giorni, comunque ci stò lavorando, anche perchè mi serve per un cliente., ma se volete andate pure avanti voi.
-
@Tuonorosso said:
ok
intanto non ci conviene dividerci i compiti noi che già ci siamo?Non sarebbe male...Allora ci organizziamo? Per favore scrivete chi è interessato, in fondo è una cosa che servirà a tutti, quindi + siamo meglio è