Utilisation de JCaptcha avec JSF

Introduction aux Captcha

Le captcha comme son nom l’indique (Completely Automated Public Turing test to tell Computers and Humans Apart) est un moyen simple de protéger son site de soumissions automatiques effectuées par des robots depuis l’autre bout du monde et ainsi de s’assurer que l’on a bien a faire à un utilisateur “humain”. Par exemple de nombreux blogs et forums sont la cibles de soumissions de post sans aucun rapport avec la discussion mais contenant des liens vers des sites d’ailleurs peu recommandables.

Le captcha est un système de question-réponse qui nécessite un minimum de réflexion pour ne pas pouvoir être automatisé.
La force du captcha réside donc d’une part dans l’impossibilité pour un algorithme de résoudre la question et d’autre part sa facilité d’interprétation pour que tout être humain puisse répondre à la question.

Plusieurs déclinaisons du Captcha existent (reconnaissance d’images, opérations arithmétiques, reconnaissances vocales) mais nous ne nous intéressons qu’au plus commun basé sur la reconnaissance de caractères dans une image. Pour constituer un bon captcha, l’image ne doit pas être décomposable facilement auquel cas un programme pourrait analyser l’image, découper les zones de texte et identifier les caractères. Voilà pourquoi ces captchas ont la particularité d’être écrits bizarrement voire parfois impossible à lire du fait des polices utilisés, des lettres qui se chevauchent ou encore à cause du fond de l’image.
Captcha Texte
Le principe du captcha réside également dans le découplage entre les informations serveurs et les informations clients : la réponse est stockée côté serveur et ne doit pas apparaitre côté client en dehors de la représentation de l’image : nom de l’image, champ caché, paramètre dans l’url, etc… sinon l’information est facilement accessible sans intervention humaine. Ensuite la réponse envoyée par le client est comparé à la réponse côté serveur.

Utilisation de JCaptcha pour vos sites web en Java

JCaptcha est un framework Java open source qui permet d’implémenter très rapidement une solution de Captcha et permet dans un deuxième temps de gérer plus finement des Captcha.
Je détaille ici la conception d’un formulaire d’enregistrement sur une page JSF utilisant JCaptcha 2.0 pour empêcher les inscriptions automatiques.

Par rapport au projet JSF vous devez ajouter 4 librairies disponibles sur le site officiel du projet JCaptcha :
* jcaptcha-api-1.0.jar
* jcaptcha-2.0-alpha-1-SNAPSHOT.jar
* jcaptcha-integration-simple-servlet-2.0-alpha-1-SNAPSHOT.jar
* filters-2.0.235.jar

Modifier votre fichier web.xml pour ajouter la servlet JCaptcha. Votre fichier doit ressembler en gros à ceci :

le fichier web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns="http://java.sun.com/xml/ns/javaee" 
        xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
        http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
	id="WebApp_ID" version="2.5">
	<display-name>Test App</display-name>
 
	<servlet>
		<servlet-name>jcaptcha</servlet-name>
		<servlet-class>com.octo.captcha.module.
                 servlet.image.SimpleImageCaptchaServlet</servlet-class>
	</servlet>
	<servlet-mapping>
		<servlet-name>jcaptcha</servlet-name>
		<url-pattern>/faces/jcaptcha.jpg</url-pattern>
	</servlet-mapping>
 
	<servlet>
		<servlet-name>Faces Servlet</servlet-name>
		<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
		<load-on-startup>1</load-on-startup>
	</servlet>
	<servlet-mapping>
		<servlet-name>Faces Servlet</servlet-name>
		<url-pattern>/faces/*</url-pattern>
	</servlet-mapping>
 
        <welcome-file-list>
		<welcome-file>index.jsf</welcome-file>
		<welcome-file>index.xhtml</welcome-file>
	</welcome-file-list>
</web-app>

Comme vous le voyez la servlet jcaptcha est mappée sur le pattern /faces/jcaptcha.jpg, ainsi l’appel de cette ressource sera redirigé vers la servlet JCaptcha.

le formulaire d’enregistrement

La page register.xhtml est liée au backing bean registrationBean et contient le formulaire avec les champs à renseigner et en bas, l’insertion du captcha via l’appel à la servlet en appelant la ressource jcaptcha.jpg.

<h:form name="register">
<table>
	<tr>
		<td>Prénom</td>
		<td><h:inputText value="#{registrationBean.firstName}"
			required="true" /></td>
	</tr>
	<tr>
		<td>Nom</td>
		<td><h:inputText value="#{registrationBean.lastName}"
			required="true" /></td>
	</tr>
	<tr>
		<td>Nom d'utilisateur</td>
		<td><h:inputText value="#{registrationBean.username}"
			required="true" id="username" /></td>
	</tr>
	<tr>
		<td>email</td>
		<td><h:inputText value="#{registrationBean.email}"
			required="true" /></td>
	</tr>
	<tr>
		<td>password</td>
		<td><h:inputSecret value="#{registrationBean.password1}"
			required="true" /></td>
	</tr>
	<tr>
		<td>confirmer password</td>
		<td><h:inputSecret id="password2"
			value="#{registrationBean.password2}" required="true" />
		       <h:message for="password2" showSummary="false" showDetail="true" /></td>
	</tr>
	<tr>
		<td colspan="2">Code de vérification</td>
	</tr>
	<tr>
		<td colspan="2"><img src="jcaptcha.jpg" /><h:inputText
			name="jcaptcha" id="jcaptcha" required="true">
			<f:validator validatorId="captchaValidator" />
			</h:inputText> <h:message for="jcaptcha" styleClass="error" /></td>
	</tr>
	<tr>
		<td colspan="2"><h:commandButton value="Valider"
			action="#{registrationBean.register}" /></td>
	</tr>
</table>
</h:form>

La vérification du captcha se fait grâce à un validator JSF (validatorId=”captchaValidator”).

Le validator du captcha

Nous allons définir un validator personnalisé qui implémente bien sûr l’interface Validator de JSF.
N.B. nous récupérons la requête via le SecurityContext car nous utilisons Spring-Security pour gérer l’identification. Il faudra remplacer cette variable par l’objet approprié si Spring-Security n’est pas utilisé.

package validator;
 
import javax.faces.application.FacesMessage;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.validator.Validator;
import javax.faces.validator.ValidatorException;
import javax.servlet.http.HttpServletRequest;
 
import org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestWrapper;
 
import com.octo.captcha.module.servlet.image.SimpleImageCaptchaServlet;
 
public class CaptchaValidator implements Validator {
 
	public static final String MATCHING_ERROR_MESSAGE = "Code de validation incorrect";
 
	@Override
	public void validate(FacesContext arg0, UIComponent arg1, Object arg2)throws ValidatorException {
 
		try {
			String userCaptchaResponse = (String)arg2;
			boolean captchaPassed = SimpleImageCaptchaServlet.validateResponse((HttpServletRequest) ((SecurityContextHolderAwareRequestWrapper)arg0.getExternalContext().getRequest()).getRequest(), userCaptchaResponse);
			if(!captchaPassed){
				throw new ValidatorException(new FacesMessage(MATCHING_ERROR_MESSAGE, MATCHING_ERROR_MESSAGE));
			}
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}

Ajouter le validator à la configuration de JSF

Rajouter dans faces-config.xml entre les balises les balises suivantes

<validator>
	<validator-id>captchaValidator</validator-id>
	<validator-class>validator.CaptchaValidator</validator-class>
</validator>

Et voilà, vous avez implémenté en seulement quatre étapes un captcha dans vos pages.

About Matthieu

Hello, I joined Java-Hoster in 2009. After my engineering studies in France, I worked for several companies including some well known Natixis , Airbus and Air France . Now I am more focused and involved on Java open-source projects and of course in Java-Hoster which makes me learn a lot and feed me as well :-D I am also responsible for this blog, so if you have something to say about it feel free to contact me. Cheers.
This entry was posted in Java course and tagged , , , , . Bookmark the permalink.

2 Responses to Utilisation de JCaptcha avec JSF

  1. hono says:

    Hi thanks a lot for sharing !

    I.was just implementing the same thing JSF+Spring+Hibernate+Spring security and I wanted to put something like a captcha in my site.

    Regards,
    hono

  2. java says:

    Merci pour votre aide, maintenant on peut choisir nous même les sites qu.on veut lier avec notre propre site.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>