Captcha: Una JSP con controllo Immagine

Effettuare su pagine web controlli basati sulle immagini
G.Morreale

Introduzione:

Diverse e diverse volte sicuramente vi siete trovati davanti una pagina di registrazione, login, o download nella quale viene richiesta la digitazione dei caratteri presenti in un immagine.

Tale test ha lo scopo di verificare se l'utente è un essere umano e non un computer.

L'acronimo inglese CAPTCHA riassume in una parola il concetto appena esposto.

"Completely Automated Public Turing test to tell Computers and Humans Apart" (Test di Turing pubblico e completamente automatico per distinguere computer e umani)


Implementare tale controllo in una pagina JSP

Al fine di inserire tale controllo all'interno di una pagina JSP, è necessario l'uso di una libreria in grado di generare l'immagine e fornire in un qualche modo il dato generato sottoforma di variabile.

La libreria che viene utilizzata nell'esempio è scaricabile da:

L'Esempio

Creiamo un progetto Web, e generiamo due pagine JSP:

  • index.jsp - che contiene il controllo
  • protetta.jsp - che è visualizzabile solo se l'utente riporta correttamente il contenuto dell'immagine su un campo di testo.

Aggiungiamo tra le librerie di progetto il jar scaricato dal precedente link.

Dividiamo ora l'esempio in due parti:

  • La generazione dell'immagine
  • Il controllo

La generazione dell'immagine

L'immagine è generata da una servlet la cui classe si trova all'interno della libreria katpcha.
Tale classe esattamente si trova nel seguente percorso:

com.google.code.kaptcha.servlet.KaptchaServlet

Bisogna però rendere disponibile la servlet configurando correttamente l'elemento e il suo mapping sul file xml.
Tale configurazione è fattibile inserendo le seguenti righe nel file web.xml

    <servlet>
        <servlet-name>Kaptcha</servlet-name>
        <servlet-class>com.google.code.kaptcha.servlet.KaptchaServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>Kaptcha</servlet-name>
        <url-pattern>/Kaptcha</url-pattern>
    </servlet-mapping>


Il primo nodo serve a dichiarare una servlet di nome Kaptcha corrispondente alla classe com.google.code.kaptcha.servlet.KaptchaServlet

Il secondo nodo invece serve a indicare su quale url deve rispondere la servlet.

La servlet è quindi ora configurata, è quindi possibile effettuare già il deploy dell'applicazione (es. su localhost) e richiamare l'url Kaptcha al fine di generare un immagine (es. prova con http://localhost/ContextPathProgetto/Kaptcha).

L'output dovrebbe essere simile a questo:


Quindi il codice della pagina index.jsp potrebbe essere simile al seguente:

<%@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>Esempio Captcha</title>
    </head>
    <body>
    <h1>Esempio Captcha</h1>
    <img src="Kaptcha" alt=""/>    
    <br />
    <form action="protetta.jsp">
        <label>Ricopia correttamente il testo: </label><br />
        <input type="text" name="kaptcha" value="" />
    </form>   
    </body>
</html>

Banalmente viene richiamata la servlet per generare l'immagine e viene mostrata all'utente una textbox per inserire il valore.
Il metodo action richiama la pagina protetta nella quale inseriremo il controllo.


Il controllo

Partiamo dal presupposto che la servlet Kaptcha non appena genera l'mmagine inserisce il corrispettivo testo all'interno di una variabile di sessione.
Tale variabile di sessione è identificabile dalla chiave com.google.code.kaptcha.Constants.KAPTCHA_SESSION_KEY

Quindi adesso credo risulti ovvio come chiudere il cerchio effettuando il controllo tra il testo digitato e quello generato.
Non si fà altro che ottenere il parametro GET o POST inserito dall'utente e confrontarlo con quello inserito dalla servlet Captcha nella sessione.

In caso di controllo positivo si procede tenendo conto che l'utente è un essere umano, in caso contrario si richiede la digitazione del testo o si  ridirige il client verso una pagina di errore.

Riassumendo il tutto con del codice sorgente:

<%@page contentType="text/html"%>
<%@page pageEncoding="UTF-8"%>
<%
//ottenimento del valore generato dal captcha sottoforma di String
String kaptchaExpected = (String) session.getAttribute(com.google.code.kaptcha.Constants.KAPTCHA_SESSION_KEY);
//estrazione input dell'utente
String kaptchaReceived = request.getParameter("kaptcha");
//Matching
if (kaptchaReceived == null || !kaptchaReceived.equalsIgnoreCase(kaptchaExpected))
{
  response.sendError(500, "Non hai ricopiato correttamente il testo nell'immagine");
  return;
}
%>
<!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 Protetta dal Controllo</title>
    </head>
    <body>
        <h1>Pagina Protetta dal Controllo</h1>                
    </body>
</html>


Conclusione

Questo è un esempio base, le applicazioni e le varianti sono diverse, ma il concetto resta invariato.

Riguardo la libreria utilizzata per la generazione dei codici è possibile effettuare delle customizzazioni sull'immagine generata(vedi http://code.google.com/p/kaptcha/wiki/ConfigParameters ).

1 comment:

Unknown said...

Grazie mille, articolo semplice e comprensibile anche dai neofiti come me.

Saluti