Creare un sistema di login per accedere in un'area riservata (II Parte)
Vediamo la seconda parte dell'articolo su come creare un sistema di login sicuro con ASP. In questo articolo verrà implementato un controllo dei dati nel database e login automatico.
Il progetto
Al sistema di login realizzato nell'articolo precedente, ora verrà implementato un controllo dei dati nel database e il login automatico
Dati:
Utente 1
Username: lorenzo
Password: pascucci
Utente 2
Username: mario
Password: gds933f
Utente 3
Username: rosa
Password: 489das0u3
Le pagine utilizzate
Le pagine utilizzate per questo sistema sono le stesse utilizzate nella precedente lezione con alcune modifiche nel modulo e nella pagina di login. E' stata inoltre introdotta una seconda pagina da proteggere solo per rendere l'esempio piu' completo.
Utilizzando questo sistema l'utente potrà dopo il primo accesso:
- accedere le volte successive direttamente in una pagina protetta (senza fare il login)
- accedere al modulo trovando i dati di accesso già inseriti
Tutto questo grazie all'utilizzo dei Cookies. Il cookie permette di memorizzare dati importanti sul computer dell'utente. Sono spesso utilizzati appunto per i sistemi di autenticazione automatica.
Il modulo
Il modulo sarà necessario modificarlo in 2 punti:
- i campi text box
- la gestione degli errori
Vediamo come e perchè.
Un'importante funzionalità di un sistema di autenticazione è ricordare i dati di accesso nel modulo di login. Quindi dovremmo modificare i valori predefiniti dei 2 text box (campi di testo) inserendo 2 semplici istruzioni asp che prelevano i dati dal cookie (che verrà creato dalla pagina di login), se il cookie non è ancora stato creato (perché non è ancora stato effettuato alcun accesso) i campi risulteranno vuoti.
Per ricavare i dati da un cookie è necessario utilizzare l'istruzione:
Request.Cookies("nome")("nomevar")
dove nome è il nome del cookie e nomevar è il nome della variabile, in quanto uno stesso cookie può contenere piu' informazioni, in questo caso 3:
- username
- password
- data di scadenza del cookie
Inoltre dalla gestione degli errori sarà necessario eliminare l'errore 102 in quanto non è previsto piu' questo controllo, infatti se i dati memorizzati nel cookie dell'utente che accede sono corretti è possibile entrare nelle pagine riservate da qualsiasi pagina.
Codice 8.1
<html><body><!--www.webmasterpoint.org--><!-- INIZIO Gestione visualizzazione errori --><%err = Cint(Request.QueryString("err"))If err > 100 then%><p align="center"><font face="Verdana" size="1" color="#FF0000"><b>IMPORTANTE:</b></font><font face="Verdana" size="1"><b>Errore </b><%Select Case errCase 101Response.Write("UsernamePassword non corretti")Case 103Response.Write("Username e Password non possono contenere caratteri speciali per motivi di sicurezza")End Select%></font></p><%End if%><!-- FINE Gestione visualizzazione errori --><div align="center"><center><form method="POST" action="lez08_index.asp"><table border="1" width="438" height="29"><tr><td width="131" height="16"><font face="Verdana" size="2">Username:</font></td><td width="301" height="16"><input type="text" name="username" size="20" value="<%=Request.Cookies("entra")("username")%>"></td></tr><tr><td width="131" height="13"><font size="2" face="Verdana">Password:</font></td><td width="301" height="13"><input type="password" name="password" size="20"value="<%=Request.Cookies("entra")("password")%>"></td></tr><tr><td width="438" height="1" colspan="2"><p align="center"><input type="submit" value="Login >>>" name="B1"></td></tr></table><input type="hidden" name="tipo" value="login"></form></center></div></body></html>
Il cuore dello script
Il codice e la logica con cui viene effettuato il controllo dei dati, come è stato già anticipato, è leggermente differente, vediamo le modifiche apportate:
- controllo del login dal modulo eliminato
- memorizzazione su cookie
- controllo dati su database
- controllo dei dati memorizzati sul cookie
Con questo sistema non è necessario effettuare il login esclusivamente dal modulo. Infatti grazie all'utilizzo dei cookie è possibile accedere all'area riservata da una qualsiasi sua pagina.
La memorizzazione di un cookie è molto semplice:
Response.Cookies("nome")("nome")
Quindi basta fare: Response.Cookies("nome")("nome") = valore.
Codice 8.2
<%'*******************************************************'** www.webmasterpoint.org'*******************************************************'Funzione che controlla l'inserimento 'di caratteri accettabili o menopublic function check_nick (allow, nick) nick = nick check_nick = true for i = 1 to len(nick) if instr(allow, mid(nick,i,1)) = 0 then check_nick = false nextend function'Controllo se è già stato effettuato l'accessoIf Session("permesso_entrata") <> True then 'Controllo se è stato effettuato l'accesso dal modulo di login Dim tipo tipo = Request.Form("tipo") 'Acquisisco i dati di accesso Dim username, password username = Trim(Request.Form("username")) password = Trim(Request.Form("password")) 'Controllo l'eventuale inserimento di caratteri 'speciali (non sono autorizzati, per motivi di sicurezza) if check_nick ("abcdefghijklmnopqrstuvwxyz -->-->ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789", username) = false then response.redirect("lez08_modulo.asp?err=103") end if if check_nick ("abcdefghijklmnopqrstuvwxyz -->-->ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789", password) = false then response.redirect("lez08_modulo.asp?err=103") end if 'Se è stato effettuato il login dal modulo entra If tipo = "login" then Response.Cookies("entra")("username") = username Response.Cookies("entra")("password") = password Response.Cookies("entra").Expires = date()+365 End If 'Connessione al database Set db = Server.CreateObject("ADODB.Connection") db.Open "provider=microsoft.jet.oledb.4.0;data source=" _& Server.MapPath("lez08_iscritti.mdb") 'Controllo dei dati inseriti nel modulo per il 'riconoscimento con un database us = Request.Cookies("entra")("username") ps = Request.Cookies("entra")("password") Set rsLogin = db.Execute("SELECT * FROM utenti WHERE _ UserName = '" & us & "' AND Password = '" & ps & "'") If rsLogin.EOF Then Session("permesso_entrata") = False Response.Redirect "lez08_modulo.asp?err=101" Else Session("permesso_entrata") = True End IfEnd If%>
L'archivio (chiamato lez08_iscritti.mdb) è così strutturato:
Un'unica tabella chiamata utenti, con 1 campo contatore (ID) e 3 campi testo (di 50 car).
Vediamo in modo particolare come avviene il controllo sul database.
E' necessario prima di tutto effettuare la connessione al database
'Connessione al database Set db = Server.CreateObject("ADODB.Connection") db.Open "provider=microsoft.jet.oledb.4.0;data source=" & Server.MapPath("lez08_iscritti.mdb")
Memorizziamo in due variabili l'username e la password presenti nel cookie
'Controllo dei dati inseriti nel modulo per il 'riconoscimento con un database us = Request.Cookies("entra")("username") ps = Request.Cookies("entra")("password")
Attraverso una query SQL di selezione cerco nella tabella utenti se esiste un record che abbia i campi username e password come i valori prelevati dal cookie.
Set rsLogin = db.Execute("SELECT * FROM utenti WHERE UserName = '" & us & "' AND Password = '" & ps & "'")
Se non esistono (EOF = End Of File)
If rsLogin.EOF Then
Imposta la Sessione a False, ovvero l'utente non potrà accedere e sarà rimandato al modulo.
Session("permesso_entrata") = False Response.Redirect "lez08_modulo.asp?err=101" Else
Imposta la Sessione a True, ovvero l'utente potrà accedere all'area riservata
Session("permesso_entrata") = True End If.
Autenticazione ibrida
Uno dei migliori sistemi di autenticazione è unire l'autenticazione Http a quella con il database. A volte capita di effettuare l'accesso ad un sito web utilizzare una finestra di dialogo di Windows che chiede l'inserimento di Username e Password che verranno criptati e se corrispondono ai dati di un utente Windows (registrato nel server) si avrà il permesse di accedere all'area riservata. Questo però è limitativo e permette un accesso esclusivamente ad amministratori e responsabili del sito.
Se si vuol utilizzare un sistema del genere per tutti gli utenti è necessario utilizzare questo sistema interfacciato ad un database.
Autenticazione di base
Vediamo i passaggi principali di questa autenticazione:
- Richiesta pagina protetta
- Il server risponde con il codice 401 Non Autorizzato
- Viene visualizzata una finestra di dialogo che chiede i dati di accesso
- Il browser invia i dati inseriti con un'intestazione chiamata AUTHORIZATION in modo criptato
- Il server decripta i dati passati e controlla se sono esatti
- Se corretti l'utente potrà accedere a tutte le pagine che richiedono il permesso (senza inserire ogni volta i dati).
Richiedere l'autenticazione di base
E' necessario innanzitutto controllare se l'intestazione AUTHORIZATION ha assegnato un valore, se non lo ha viene inviato il codice di stato 401 per far visualizzare una finestra di dialogo.
Codice 8.3
<%'Memorizza intestazione AUTHORIZATIONautorizzazione = Request.ServerVariables("HTTP_AUTHORIZATION")'Controllo, se è vuota accesso vietatoIf Trim(autorizzazione) = "" Then 'Imposta stato Response.Status = "401 Not Authorized" 'Chiede di aprire finestra di dialogo per 'inserimento dati di acccesso Response.AddHeader "WWW-Authenticate", "Basic realm=""localhost""" Response.EndEnd If'Se si viene riconosciuti, continua e visualizza l'intestazione.%><html><head><title>Protezione area riservata - Lezione 8</title><body>L'intestazione Authorization: <%=autorizzazione%></body></html>
I passaggi dell'intestazione AUTHORIZATION vengono tutti codificati nel metodo di codifica (abbastanza superato) base64, molto semplice, ma comunque valido, è tuttavia possibile utilizzare anche altri sistemi preferiti o software di terze parti.
Autenticazione ibrida
Vediamo ora il codice per effettuare un'autenticazione ibrida, ovvero l'auteticazione di base che controlla i dati di accesso in un database.
Codice 8.4
<%autorizzazione = Request("HTTP_AUTHORIZATION")'*******************************************************'** www.webmasterpoint.org'*******************************************************'** INIZIO DECODIFICASET UUEncode = Server.CreateObject("Scripting.Dictionary")For conta = 0 to 63 Select CASE conta CASE 0 offset = 65 CASE 26 offset = 71 CASE 52 offset = -4 End Select UUEncode( Chr(conta+offset)) = contaNextFunction Decodifica(stringa) For codice = 1 to Len(stringa) Step 4 numeroByte = 3 gruppoByte = 0 For ContaTesto = 0 to 3carattere = Mid(stringa, codice + ContaTesto,1)If carattere = "=" then numeroByte = numeroByte -1 ByteAttuale = 0Else ByteAttuale = UUEncode(carattere)End IfgruppoByte = 64 * gruppoByte + ByteAttuale Next For contaB = 1 To numeroByteSelect CASE contaB CASE 1: carattere = gruppoByte 65536 CASE 2: carattere = (gruppoByte AND 65535) 256 CASE 3: carattere = (gruppoByte AND 255)End SelectDecodifica = Decodifica & Chr(carattere) Next NextEnd Function'** FINE DECODIFICA'Controllo, se è vuota accesso vietatoIf Trim(autorizzazione) = "" Then Response.Status = "401 Not Authorized" Response.AddHeader "WWW-Authenticate", "Basic realm=""localhost""" Response.EndEnd Ifautorizzazione= Trim(Mid(autorizzazione,6))autorizzazione= Decodifica(autorizzazione)autoDivisa = Split(autorizzazione, ":")username = autoDivisa(0)password = autoDivisa(1)Response.Write(username)Response.Write(password)Response.End'Connessione al databaseSet db = Server.CreateObject("ADODB.Connection")db.Open "provider=microsoft.jet.oledb.4.0;data source=" _& Server.MapPath("lez08_iscritti.mdb")Set rsLogin = db.Execute("SELECT * FROM utenti WHERE UserName = '" _& username & "' AND Password = '" & password & "'")If rsLogin.EOF Then Response.Status = "401 Not Authorized" Response.AddHeader "WWW-Authenticate", "Basic realm=""localhost""" Response.EndElse nomeUtente = RsLogin("nome")End If'Se si viene riconosciuti, continua e visualizza l'intestazione.%><html><head><title>Protezione area riservata - Lezione 8</title><body>Benvenuto <%=nomeUtente%></body></html>
Le righe di codice fino a '** INIZIO DECODIFICA permetto di effettuare la decodifica in base64, le restanti sono di semplice comprensione.
Viene effettuato un controllo se esiste un'intestazione AUTHORIZATION, se è vuota visualizza la finestra di dialogo, se è piena effettua la decodifica e controlla i dati nel database se sono esatti, se sono errati visualizza nuovamente la finestra di dialogo.
Tutto questo deve avvenire in una cartella che ha esclusivamente i permessi di Accesso Anonimo (Allow Anonymous Access).
- Articolo precedente Realizzare un sistema di login (I Parte)
- Articolo successivo Creare una directory di link