Articoli Referenze Script FAQ Downloads Menu Javascript Ricette Cocktail Corsi online Registrazione domini Area Aziende



Un sistema di login in ASP

Home + Articoli + Sicurezza + Articolo # 148
Autore: Luca Ruggiero

Concesso in esclusiva a Mr.Webmaster. Vietata la riproduzione.


Introduzione

In due articoli precedenti abbiamo visto dei sistemi di login in ASP basati su XML oppure sul confronto tra due costanti. Vediamo adesso un sistema basato su database e vediamo come renderlo sicuro contro problemi di sicurezza noti come l'SQL Injection oppure il banale tentativo di uno smanettone che, magari per gioco, prova a frodare il sistema ed autenticarsi in maniera illegittima.

Costruiamo innanzitutto nel database di prova (ad esempio database.mdb) la tabella utenti corredata dai campi id (Contatore), username (Testo, lunghezza 10) e password (Testo, lunghezza 10). Naturalmente ognuno poi aggiungerà alla tabella tutti i dati personali degli utenti che ritiene opportuno, ma per l'esempio ci limitiamo a quelli necessari all'autenticazione.

La pagina di login

Creiamo adesso il file login.asp che conterrà sia il modulo di inserimento delle credenziali d'accesso che lo script ASP per il controllo sull'autenticazione.

Segue il codice completo:
<%@LANGUAGE = VBScript%>
<%
 Option Explicit
 On Error Resume Next
 Response.Buffer = True
%>
<html>
<head>
<title>Un sistema di login in ASP</title>
</head>
<body>

<h1>Un sistema di login in ASP</h1>

<form method="post" action="login.asp">
Username<br>
<input type="text" name="username"><br><br>
Password<br>
<input type="password" name="password"><br><br>
<input type="submit" name="login" value="Login">
</form>

<%
 If Request.Form("login") <> "" Then
  Dim username, password, re
  username = Request.Form("username")
  password = Request.Form("password")
  Set re = New RegExp
  re.Pattern = "^[a-z0-9]+$"
  If re.Test(username) = False Or re.Test(password) = False Then
   Response.Write "Inserire username e password alfanumeriche"
  ElseIf Len(username) < 6 Or Len(password) < 6 Then
   Response.Write "Inserire username e password di almeno 6 caratteri"
  Else
   Dim sc, cn, rs, sql
   sc = "driver={Microsoft Access Driver (*.mdb)};dbq="
   sc = sc & Server.MapPath("database.mdb")
   Set cn = Server.CreateObject("ADODB.Connection")
   Set rs = Server.CreateObject("ADODB.Recordset")
   cn.Open sc
   sql = "SELECT id, password FROM utenti "
   sql = sql & "WHERE username = '" & username & "'"
   rs.Open sql, cn, 1
   If rs("password") = password Then
    Session("userid") = rs("id")
    Response.Write "Autenticazione effettuata con successo"
   Else
    Response.Write "Account inesistente"
   End If
   rs.Close
   cn.Close
   Set rs = Nothing
   Set cn = Nothing
  End If
 End If
%>

</body>
</html>
Passiamo adesso alla spiegazione dei singoli passaggi.

Controlliamo innanzitutto che il modulo sia stato inviato e lo facciamo rigorosamente col metodo post, per non lasciare mai traccia nella cronologia del browser delle credenziali d'accesso.

A condizione soddisfatta recuperiamo username, password e creiamo un'espressione regolare per filtrare tutti i caratteri non alfanumerici. Questo è un passo necessario ed anche se l'utente non potrà mai scegliere una username o una password con caratteri speciali (ad esempio: '&mia_username'$ poco indovinabile da un hacker) ci semplifichiamo la vita in fase di controllo e di rispetto della sicurezza.

Verifichiamo che le credenziali di accesso rispettino i canoni di sicurezza appena descritti, verifichiamo che le credenziali inserite non siano minori di 6 caratteri e, volendo, possiamo impostare altri controlli prima di passare i dati alla query. E' importante, a questo punto, prevedere gli stessi controlli in fase di iscrizione.

Siamo arrivati al caso in cui tutte le condizioni sono state soddisfatte e possiamo accedere al database per verificare l'autenticità delle credenziali e consentire, o meno, l'accesso all'utente che ne fa richiesta.

Lanciamo una query che estrae l'id e la password verificando che corrispondano alla username inserita nel modulo. A questo punto verifichiamo che il campo password estratto sia uguale alla password inserita dall'utente. In caso affermativo creiamo la sessione (valorizzandola con l'id dell'utente) oppure, in caso contrario, avvisiamo l'utente che il tentativo di accesso non è andato a buon fine.

Sistema alternativo per la query di autenticazione

Il sistema utilizzato per la costruzione della query e la verifica delle credenziali di accesso non è quello usato dalla stragrande maggioranza dei programmatori ed è molto poco visto, o per nulla, negli articoli come questo che spiegano i sistemi di autenticazione in ASP. Tuttavia è il sistema consigliato dai manuali di logica di sicurezza in fase di autenticazione.

Rivediamo la porzione di codice utilizzata e già spiegata:
sql = "SELECT id, password FROM utenti "
sql = sql & "WHERE username = '" & username & "'"
rs.Open sql, cn, 1
If rs("password") = password Then
 Session("userid") = rs("id")
 Response.Write "Autenticazione effettuata con successo"
Else
 Response.Write "Account inesistente"
End If
rs.Close
Confrontiamola con quella classica, utilizzata dalla maggior parte degli utenti:
sql = "SELECT id FROM utenti WHERE username = '" & username & "'"
sql = sql & " AND password = '" & password & "'"
rs.Open sql, cn, 1
If rs.EOF = False Then
 Session("userid") = rs("id")
 Response.Write "Autenticazione effettuata con successo"
Else
 Response.Write "Account inesistente"
End If
rs.Close
In sostanza passiamo alla query, in fase di ricerca, una coppia di valori utili all'autenticazione; se qualcosa va storto in fase di filtro posso assicurare che non è necessario un hacker professionista, ma basta uno smaliziato appena esperto per bucare il sistema!

La pagina di logout

La pagina di logout è molto semplice: è sufficiente (caso 1) svuotare il valore della sessione creata, oppure (caso 2) distruggere tutte le sessioni attive sul server per l'utente che ne fa richiesta.

Caso 1:
<%@LANGUAGE = VBScript%>
<%
 Session("userid") = ""
 Response.Write "Grazie per essere stato con noi"
%>
Caso 2:
<%@LANGUAGE = VBScript%>
<%
 Session.Abandon
 Response.Write "Grazie per essere stato con noi"
%>
I due sistemi si equivalgono e la differenza sostanziale tra i due è che nel primo caso distruggiamo solo la sessione che ci interessa distruggere, mentre nel secondo le distruggiamo tutte, anche quelle che, potenzialmente, potrebbero essere utili. Suggerisco quindi il primo dei due sistemi.

Controllo sulle pagine protette

Anche la verifica della navigazione sulle pagine protette è piuttosto semplice: è sufficiente verificare che la sessione creata in fase di login sia attiva.

Vediamo il codice di una pagina protetta "tipo":
<%@LANGUAGE = VBScript%>
<%
 Dim userid
 userid = Session("userid")
 If IsNumeric(userid) = False Or userid < 1 Or userid = "" Then
  Response.Write "Accesso negato"
  Response.End
 End If
%>
<html>
...
Verifichiamo che la sessione abbia valore numerico, che non sia inferiore ad 1 (non può esserlo, dato che il contatore di una tabella inizia sempre da 1) e, non contenti, verifichiamo anche che non abbia valore vuoto dato che, per qualche strano caso, il valore potrebbe passare come stringa e non come numero.

Se la triplice condizione non viene soddisfatta avvisiamo l'utente e e blocchiamo l'esecuzione ed il caricamento della pagina. In caso contrario non entreremo affatto nella condizione e mostreremo all'utente la pagina protetta.

Conclusioni

Come detto nell'introduzione di questo articolo ci troviamo di fronte al più sicuro dei sistemi di login immaginabile attraverso un linguaggio di scripting lato server come ASP. Con i filtri ed i controlli che impostiamo rendiamo la vita impossibile a qualsiasi smanettone che tenti di entrare illegittimamente nel nostro sistema protetto, ma state pur certi che questo sistema, o anche altri sistemi più efficaci implementati direttamente sul server e non attraverso uno script, sono aggirabili tranquillamente da un hacker esperto, il quale magari non avrà mai interesse a venire a bucare proprio noi!

In precedenza ho accennato ad una serie di controlli per non passare i dati alla query qualora non siano già corretti, onde evitare inutili sforzi del server e del database ed anche per i criteri di sicurezza accennati. Quelli che ci sono vanno già bene, ma la scaletta logica completa da seguire potrebbe essere la seguente:
  • Verificare che la username non sia vuota.
  • Verificare che la password non sia vuota.
  • Verificare che la username non sia inferiore a 6 caratteri.
  • Verificare che la password non sia inferiore a 6 caratteri.
  • Verificare che la username non sia superiore a 10 caratteri.
  • Verificare che la password non sia superiore a 10 caratteri.
  • Verificare che la username sia alfanumerica.
  • Verificare che la password sia alfanumerica.
© 2008 ASP Center di Luca Ruggiero - P. IVA 05564851219 - Utenti online: 12 - Disclaimer | Pubblicità | Supportaci | Staff | Contatti
  Appunti PHP | Giornale Webmaster | Mr.Webmaster | Download | DevSpy.com | ASPCode.it | ClaudioGarau.it | Webmaster Facile | Come Faccio | AlVerde.net | CodiceFacile.it | I Programmatori | By Luciani | VoiceXML Italian User Group | Giochi | Extro Web Site | Morpheus Web | AG Web Solutions | Net-Free | PC Sicuro | PC Self | Tutorial Web | Dablones