Voici une application capable de faire la difference entre un humain et un bot. Les formulaires d’inscription ont souvent besoin de ce genre d’outils afin de securiser les serveurs. l’idée est de generer une image contenant un texte, et de le comparer à une valeur saisie par l’utilisateur.
Il est en effet très difficile de faire un script capable de passer ce genre de securité simple à mettre en oeuvre.
Voici un exemple d’image générée par notre programme :

Voici le principe de fonctionnement :

Pour fonctionner l’application est composée de :
Mon exemple tourne actuellement sur une architécture TomCat 5.5.7, JDK 5.0.
1) Le code de ma servlet :
/* * Created on 28 mars 2005 * */ package com.utils.dynimage; import javax.servlet.ServletException; import javax.servlet.http.*; import java.util.*; import java.awt.*; import java.io.*; import java.awt.image.*; import java.awt.font.*; import javax.imageio.*; import java.awt.geom.*; /** * @author Eric * */ public class GetDynImage extends HttpServlet { public void init() throws ServletException { //System.out.println("Servlet started"); } public void destroy() { //System.out.println("Servlet is stopping now"); } protected void doPost(HttpServletRequest arg0, HttpServletResponse arg1) throws ServletException, IOException { doGet(arg0, arg1); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String text = getRandomText(); // Sauvegarde de la string en session HttpSession session = request.getSession(true); session.setAttribute("dynImageTxt", text); String font_file = getServletContext().getRealPath ("WEB-INF/ttf/acmesa.ttf" ); float size = 50.0f; Color background = Color.white; Color color = Color.black; try { Font font = Font.createFont(Font.TRUETYPE_FONT, new FileInputStream(font_file)); font = font.deriveFont(size); BufferedImage buffer = new BufferedImage(1,1,BufferedImage.TYPE_INT_RGB); Graphics2D g2 = buffer.createGraphics(); g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); FontRenderContext fc = g2.getFontRenderContext(); Rectangle2D bounds = font.getStringBounds(text,fc); // Calcul de la taille du texte int width = (int) bounds.getWidth(); int height = (int) bounds.getHeight(); // Preparation de la sortie buffer = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); g2 = buffer.createGraphics(); g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); g2.setFont(font); g2.drawString(text,0,(int)-bounds.getY()); // Set content type et get de l'output stream response.setContentType("image/jpeg"); OutputStream os = response.getOutputStream(); // Output en PNG de l'image ImageIO.write(buffer, "jpg", os); os.close(); } catch (Exception e) { // Traitement Erreur } } /*** * * Method used to get a random UpperCase text of 5 letters. * * @return String text. */ private String getRandomText () { // Génération d'un texte aléatoire int length = 5; char[] array = new char[ length ]; char[] chars = new char[26]; //for (int i = 0; i < 26; i ++) {chars[i] = (char) (97 + i);chars[i + 26] = (char) (65 + i);} // Creation d'une table avec les majuscules de l'alphabet. for (int i = 0; i < 26; i ++) { chars[i] = (char) (97 + i); } Random random = new Random (); for (int i = 0; i < length; i ++) { array[i] = chars[random.nextInt (chars.length)]; } // Parametres par défaut return new String (array); } }
2) La vérification de la valeur :
// Lecture de la session, de l'attribut captcha HttpSession session = request.getSession(true); String value = (String) session.getAttribute("dynImageTxt"); // lecture de la valeur du champs nommé imgValue du formulaire de saisie. String formValue = request.getParameter("imgValue"); if (formValue.toLowerCase().equals(value.toLowerCase())) { // Valeur exacte !!!! } else { // Valeur fausse !!!! }
Attention : Si votre serveur est positionné derriere un load-balancer, vous devez prendre garde à le configurer de sorte que l’utilisateur tombe systématiquement sur la même machine, dans le cas contraire, la valeur en session ne correspondrait a rien.






Espace de communautaire - postez vos commentaires