Laboratorio di Sistemi Autenticazione utente mediante MySQL
Jsp [Java]
Per la comprensione del presente articolo, occorre aver assimilato i concetti esposti
nell'articolo “Prototipo autenticazione utente” (file autenticazione_2.pdf).
(Tratto da Wikipedia, l'enciclopedia libera)
Funzione MD5
L'MD5 (acronimo di Message Digest algorithm 5) è un algoritmo per la crittografia dei
dati a senso unico realizzato da Ronald Rivest (nella foto) nel 1991 e standardizzato
con la RFC 1321.
Questo tipo di codifica prende in input una stringa di lunghezza arbitraria e ne produce
in output un'altra a 128 bit (ovvero con lunghezza fissa di 32 valori esadecimali,
indipendentemente dalla stringa di input) che può essere usata per calcolare la firma
digitale dell'input. La codifica avviene molto velocemente e si presuppone che l'output
(noto anche come "MD5 Checksum" o "MD5 Hash") restituito sia univoco (ovvero si
ritiene che sia impossibile, o meglio, che sia altamente improbabile ottenere con due
diverse stringhe in input una stessa firma digitale in output) e che non ci sia
possibilità, se non per tentativi, di risalire alla stringa di input partendo dalla stringa di
output (la gamma di possibili valori in output è pari a 16 alla 32esima potenza).
Applicazione pratica dell'MD5
La crittografia tramite algoritmo MD5 viene applicata in tutti i settori dell'informatica
che lavorano con il supporto delle firme digitali o che comunque trattano dati sensibili.
Ad esempio, viene utilizzata per controllare che uno scambio di dati sia avvenuto
senza perdite, semplicemente attraverso il confronto della stringa prodotta dal file
inviato con quella prodotta dal file ricevuto. Con lo stesso metodo si può verificare se
il contenuto di un file è cambiato (funzione utilizzata dai motori di ricerca per capire se
una pagina deve essere nuovamente indicizzata). È diffuso anche come supporto per
l'autenticazione degli utenti attraverso i linguaggi di scripting Web server-side (PHP in
particolare): durante la registrazione di un utente su un portale internet, la password
scelta durante il processo verrà codificata tramite MD5 e la sua firma digitale verrà
memorizzata nel database (o in qualsivoglia contenitore di dati).
autenticazione_3.pdf
Pag. 1/17
Cozzetto ©
Laboratorio di Sistemi Autenticazione utente mediante MySQL
Jsp [Java]
Successivamente, durante il login la password immessa dall'utente subirà lo stesso
trattamento e verrà confrontata con la copia in possesso del server, per avere la
certezza dell'autenticità del login.
(Fine testo tratto da Wikipedia)
Esempio con Php
E' facilissimo costruire un piccolo esempio di utilizzo della funzione md5 in Php (md5 è
una funzione built-in del linguaggio).
File md5.php
<?php
$a="pippo";
echo ($a."=".md5($a));
?>
Collochiamo la pagina nella cartella htdocs di Xampp e digitiamo la url nel browser
http://localhost/md5.php.
Otteniamo una sequenza di 32 valori esadecimali come previsto dalla definizione vista
precedentemente.
Esempio con Jsp
In java, le cose sono leggermente più complesse. Scriviamo, come avviene
normalmente con una qualsiasi applicazione java, prima di tutto una classe (che
chiameremo MD5) e dotiamo questa classe di un metodo statico che chiameremo md5
(in minuscolo). Il metodo accetta come parametro di input una stringa e restituisce in
output una nuova stringa che rappresenta l'impronta della stringa iniziale, in accordo
autenticazione_3.pdf
Pag. 2/17
Cozzetto ©
Laboratorio di Sistemi Autenticazione utente mediante MySQL
Jsp [Java]
con la definizione.
/*
* MD5.java
*/
package it.itiscastelli.classi;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
/**
*
* @author maurizio
*/
public class MD5 {
public MD5() {
}
public static String md5(String message) throws NoSuchAlgorithmException {
// utilizziamo la classe MessageDigest del package java.security
MessageDigest md;
try {
// getInstance vuole come argomento la costante “MD5” che rappresenta
// l'algoritmo md5
md = MessageDigest.getInstance("MD5");
} catch (NoSuchAlgorithmException ex) {
throw new NoSuchAlgorithmException("Errore. Non esiste un tale
algoritmo.");
}
// stringbuffer di appoggio
StringBuffer sb = new StringBuffer();
// il metodo digest vuole come argomento un array di byte e restituisce un array
// di byte
byte[] messDig5 = md.digest(message.getBytes());
// trasformiamo l'array di byte in una stringa
for( int i = 0 ; i < messDig5.length ; i++ ) {
String tmpStr = "0"+Integer.toHexString( (0xff & messDig5[i]));
sb.append(tmpStr.substring(tmpStr.length()-2));
}
// restituiamo la stringa ottenuta da sb
return sb.toString();
} // fine metodo md5
} // fine classe MD5
autenticazione_3.pdf
Pag. 3/17
Cozzetto ©
Laboratorio di Sistemi Autenticazione utente mediante MySQL
Jsp [Java]
Poi progettiamo una piccola web application (MD5WebApp) con la quale testare il
metodo appena descritto.
File index.jsp
<%@page import="it.itiscastelli.classi.*" %>
<%@page contentType="text/html" pageEncoding="ISO-8859-2"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-2">
<title>Prova MD5</title>
<style>
body, td, tr {
font-family: Verdana, Arial, "Trebuchet MS";
font-size: 13px;
}
</style>
</head>
<body>
<h3>Hello MD5!</h3>
<%
String messaggio = "pippo";
out.println( messaggio + "=" + MD5.md5(messaggio) );
%>
</body>
</html>
autenticazione_3.pdf
Pag. 4/17
Cozzetto ©
Laboratorio di Sistemi Autenticazione utente mediante MySQL
Jsp [Java]
Come si può facilmente vedere, la stringa ottenuta è esattamente la stessa rispetto a
quella ottenuta mediante Php.
Database MySQL users_db
Prepariamo ora un database MySQL users_db e la tabella users_tbl con la seguente
struttura:
Il campo id rappresenta la chiave primaria della nostra tabella (di tipo autoincrement).
Il campo password riceverà le password criptate degli utenti mediante il metodo md5
come spiegato precedentemente. Per gestire più facilmente l'inserimento dei dati,
utilizziamo il noto applicativo PhpMyAdmin che è dotato di una comoda interfaccia
web. Prepariamo alcuni dati di prova sfruttando uno dei due applicativi (quello in Php
o quello in Jsp) descritti precedentemente.
La web application PasswordDBWebApp
Il nostro sistema di autenticazione utente è costituito da 3 classi (Utente, DAO e MD5)
e 3 ulteriori pagine web (in aggiunta a index.jsp), login.jsp, riservata.jsp, logout.jsp.
NetBeans 5.5
Ricordatevi di scaricare i driver di MySQL se usate una versione meno recente della
6.1 di NetBeans. Se invece usate NetBeans 6.1 o NetBeans 6.5, allora i driver sono già
inclusi in NetBeans e potete facilmente aggiungerli al progetto (tasto destro del
mouse sul progetto > Proprietà > Librerie > MySQL Driver). Per coloro che
disponessero invece di NetBeans 5.5, ecco la corretta procedura per aggiungere i
driver java (noti come MySQL Connector/JDBC): dal link
http://www.mysql.com/products/connector/j/ (oppure dal sito della Sun visto che
l'azienda che produce MySQL è stata appena acquisita da Sun MicroSystem)
scarichiamo il file .tar.gz o il file .zip, poi estraiamo solo il file mysql-connector-java5.1.5-bin.jar e copiamolo ora nella cartella lib (apriamo la cartella web, poi andiamo in
WEB-INF e creiamo la cartella lib all'interno). E' tutto.
autenticazione_3.pdf
Pag. 5/17
Cozzetto ©
Laboratorio di Sistemi Autenticazione utente mediante MySQL
Jsp [Java]
Ecco ora il codice del nostro applicativo:
/*
* DAO.java
*/
package it.itiscastelli.classi;
import java.sql.Connection;
import java.sql.Date;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.GregorianCalendar;
/**
*
* @author maurizio
*/
public class DAO implements java.io.Serializable {
private Connection conn;
public DAO() throws ClassNotFoundException, SQLException {
//
}
// chiusura della connessione
public void closeConn() throws SQLException {
getConn().close();
} // fine metodo closeConn()
// caricamento dei driver e apertura della connessione al database
public void openConn() throws ClassNotFoundException, SQLException {
Class.forName("com.mysql.jdbc.Driver");
System.out.println("Driver caricati.");
setConn(DriverManager.getConnection("jdbc:mysql://localhost:3306/users_db?
user=root&password="));
System.out.println("Connessione stabilita.");
} // fine metodo openConn()
public Utente cercaUtente(String username, String password) throws Exception,
SQLException {
Statement st = null;
ResultSet rs = null;
if (username.equals("") && password.equals(""))
throw new Exception("Attenzione! Non puoi lasciare username e password
vuoti.");
autenticazione_3.pdf
Pag. 6/17
Cozzetto ©
Laboratorio di Sistemi Autenticazione utente mediante MySQL
Jsp [Java]
if (username.equals(""))
throw new Exception("Attenzione! Non puoi lasciare il campo username
vuoto.");
if (password.equals(""))
throw new Exception("Attenzione! Non puoi lasciare il campo password
vuoto.");
try {
String sql="SELECT * FROM users_tbl WHERE username='"+username+"'
AND password='"+it.itiscastelli.classi.MD5.md5(password)+"'";
st=conn.createStatement();
rs = st.executeQuery(sql);
if (!rs.next()) {
// record non trovato
rs.close();
st.close();
//conn.close();
return null;
} else {
// record individuato
it.itiscastelli.classi.Utente v = new it.itiscastelli.classi.Utente();
v.setUsername(rs.getString("username"));
v.setLuogoDiNascita(rs.getString("luogo_di_nascita"));
Date dataNascita = rs.getDate("data_di_nascita");
// trasformo la data di MySQL in un oggetto
// di tipo GregorianCalendar
GregorianCalendar data = new GregorianCalendar();
data.setTime(dataNascita);
// imposto l'attributo data dell'oggetto v
v.setDataDiNascita(data);
rs.close();
st.close();
//conn.close();
return v;
} // end if
} catch (SQLException e) {
throw new SQLException("Impossibile eseguire la query o chiudere la
connessione.");
} // fine try-catch
} // fine metodo
autenticazione_3.pdf
Pag. 7/17
Cozzetto ©
Laboratorio di Sistemi Autenticazione utente mediante MySQL
Jsp [Java]
/**
* @return the conn
*/
public Connection getConn() {
return conn;
}
/**
* @param conn the conn to set
*/
public void setConn(Connection conn) {
this.conn = conn;
}
} // fine classe DAO
/*
* Utente.java
*/
package it.itiscastelli.classi;
import java.util.GregorianCalendar;
/**
*
* @author maurizio
*/
public class Utente implements java.io.Serializable {
private int id;
private String username;
private String password;
private String luogoDiNascita;
private GregorianCalendar dataDiNascita;
/** Creates a new instance of Utente */
public Utente() {
//
}
public Utente(String username, String password) {
this.username=username;
this.password=password;
}
autenticazione_3.pdf
Pag. 8/17
Cozzetto ©
Laboratorio di Sistemi Autenticazione utente mediante MySQL
Jsp [Java]
/**
* @return the id
*/
public int getId() {
return id;
}
/**
* @param id the id to set
*/
public void setId(int id) {
this.id = id;
}
/**
* @return the username
*/
public String getUsername() {
return username;
}
/**
* @param username the username to set
*/
public void setUsername(String username) {
this.username = username;
}
/**
* @return the password
*/
public String getPassword() {
return password;
}
/**
* @param password the password to set
*/
public void setPassword(String password) {
this.password = password;
}
/**
* @return the luogoDiNascita
*/
public String getLuogoDiNascita() {
return luogoDiNascita;
}
autenticazione_3.pdf
Pag. 9/17
Cozzetto ©
Laboratorio di Sistemi Autenticazione utente mediante MySQL
Jsp [Java]
/**
* @param luogoDiNascita the luogoDiNascita to set
*/
public void setLuogoDiNascita(String luogoDiNascita) {
this.luogoDiNascita = luogoDiNascita;
}
/**
* @return the dataDiNascita
*/
public GregorianCalendar getDataDiNascita() {
return dataDiNascita;
}
/**
* @param dataDiNascita the dataDiNascita to set
*/
public void setDataDiNascita(GregorianCalendar dataDiNascita) {
this.dataDiNascita = dataDiNascita;
}
} // fine classe Utente
Riportiamo qui invece di seguito le pagine web:
File index.jsp
<%@page import="it.itiscastelli.classi.*" %>
<%@page contentType="text/html" pageEncoding="ISO-8859-2"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-2">
<title>Prova MD5</title>
<style>
body, td, tr {
font-family: Verdana, Arial, "Trebuchet MS";
font-size: 13px;
}
</style>
</head>
<body>
<h3>Hello MD5!</h3>
<%
String messaggio = "pippo";
out.println( messaggio + "=" + MD5.md5(messaggio) );
%>
</body></html>
autenticazione_3.pdf
Pag. 10/17
Cozzetto ©
Laboratorio di Sistemi Autenticazione utente mediante MySQL
Jsp [Java]
File login.jsp
<%@page contentType="text/html" pageEncoding="ISO-8859-2"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-2">
<title>Pagina di login</title>
<style>
body, td, tr {
font-family: Verdana, Arial, "Trebuchet MS";
font-size: 13px;
}
</style>
</head>
<body>
<h3>Login utente</h3>
<%
// visualizza l'id di sessione per scopi di debugging
out.println("<p>Session ID: "+session.getId()+"</p>");
if (session.getAttribute("utente")!=null)
response.sendRedirect("riservata.jsp");
%>
<form name="provaFrm" action="${request.requestURI}" method="post" >
<p>Username <input type="text" name="usernameTxt" value="$
{param.usernameTxt}" /><br/>
Password <input type="password" name="passwordTxt" value="$
{param.passwordTxt}" /><br/>
<input type="submit" name="inviaBtn" value="Invia"/></p>
</form>
<%
if (request.getParameter("inviaBtn")!=null) {
it.itiscastelli.classi.DAO dao;
try {
dao=new it.itiscastelli.classi.DAO();
dao.openConn();
} catch(Exception e) {
out.println(e.getMessage());
return;
}
String username = request.getParameter("usernameTxt");
String password = request.getParameter("passwordTxt");
it.itiscastelli.classi.Utente v=null;
autenticazione_3.pdf
Pag. 11/17
Cozzetto ©
Laboratorio di Sistemi Autenticazione utente mediante MySQL
Jsp [Java]
try {
v = dao.cercaUtente(username, password);
} catch (Exception e) {
dao.closeConn();
out.println(e.getMessage());
return;
}
if (v!=null) {
session.setAttribute("utente",v);
response.sendRedirect("riservata.jsp");
}
else {
out.println("Accesso non consentito. Per cortesia, riprova a inserire
username e password.");
response.setHeader("Refresh","5; login.jsp");
} // fine if
// chiudo la connessione
dao.closeConn();
}
%>
</body>
</html>
File riservata.jsp
<%@page contentType="text/html"%>
<%@page pageEncoding="UTF-8"%>
<%@page import="java.util.GregorianCalendar" %>
<%@page import="java.util.Calendar" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Pagina riservata</title>
<style>
body, td, tr {
font-family: Verdana, Arial, "Trebuchet MS";
font-size: 13px;
}
</style>
</head>
<body>
<h3>Accesso riservato</h3>
<%
// visualizza l'id di sessione per scopi di debugging
out.println("<p>Session ID: "+session.getId()+"</p>");
autenticazione_3.pdf
Pag. 12/17
Cozzetto ©
Laboratorio di Sistemi Autenticazione utente mediante MySQL
Jsp [Java]
// se l'attributo utente non esiste
if (session.getAttribute("utente")==null) {
out.println("<p>Pagina riservata. Non puoi accedere a queste
informazioni.</p>");
out.println("<p>Tra pochi secondi verrai rediretto verso la home page.</p>");
response.setHeader("Refresh","5; login.jsp");
} else {
it.itiscastelli.classi.Utente v = (it.itiscastelli.classi.Utente)
session.getAttribute("utente");
out.println("Benvenuto "+v.getUsername()+". Accesso consentito.");
GregorianCalendar d = v.getDataDiNascita();
int giorno = d.get(Calendar.DAY_OF_MONTH);
int mese = d.get(Calendar.MONTH)+1;
int anno = d.get(Calendar.YEAR);
String dataNascita = giorno+"/"+mese+"/"+anno;
out.println("Sei nato il "+dataNascita+ " a "+v.getLuogoDiNascita()+".");
out.println("<p><a href='logout.jsp'>Logout</a></p>");
}
%>
</body>
</html>
File logout.jsp
<%@page contentType="text/html"%>
<%@page pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Pagina di logout</title>
<style>
body, td, tr {
font-family: Verdana, Arial, "Trebuchet MS";
font-size: 13px;
}
</style>
</head>
<body>
<h3>Pagina di logout</h3>
<%
// visualizza l'id di sessione per scopi di debugging
out.println("<p>Session ID: "+session.getId()+"</p>");
// se l'attributo della sessione esiste e non è nullo
if (session.getAttribute("utente")!=null) {
it.itiscastelli.classi.Utente v = (it.itiscastelli.classi.Utente)
session.getAttribute("utente");
autenticazione_3.pdf
Pag. 13/17
Cozzetto ©
Laboratorio di Sistemi Autenticazione utente mediante MySQL
Jsp [Java]
out.println("Grazie "+v.getUsername()+" di aver usato l'applicativo.");
session.removeAttribute("utente");
session.invalidate();
out.println("<p>Tra pochi secondi verrai rediretto verso la home page.</p>");
response.setHeader("Refresh","5; login.jsp");
} else {
response.sendRedirect("login.jsp");
}
%>
</body></html>
Vediamo in azione il nostro applicativo:
Fig. 1 – Login con username e password errati
autenticazione_3.pdf
Pag. 14/17
Cozzetto ©
Laboratorio di Sistemi Autenticazione utente mediante MySQL
Jsp [Java]
Fig. 2 – Messaggio di errore: accesso non consentito
Fig. 3 – Dati corretti
autenticazione_3.pdf
Pag. 15/17
Cozzetto ©
Laboratorio di Sistemi Autenticazione utente mediante MySQL
Jsp [Java]
Fig. 4 – Accesso consentito
Fig. 5 – Logout dall'applicativo
autenticazione_3.pdf
Pag. 16/17
Cozzetto ©
Laboratorio di Sistemi Autenticazione utente mediante MySQL
Jsp [Java]
Fig. 6 – L'ID di sessione è cambiato
autenticazione_3.pdf
Pag. 17/17
Cozzetto ©