How can i prevent automated registrations using a (captcha) image?

In your user registration pages you may want to provide a generated image, which the user will be required to read and type its contents onto a text box. This will prevent automated bots etc. from filling up the form doing fake registrations.

What you need is:

A image tag in your user form, the src of it should point to a program (.jsp,struts-action etc.) which returns a randomly image (which has text), but before returning this program must store the image text in Session too, so that it when the form is submitted, you can retrieve what the user typed for the image text and compare it against what i stored in the session.

Not clear?

Ok your user form looks like this:

<form action=”/registerUser”>

Email: <input type=”text” name=”email”>

Name: <input type=”text” name=”thename”>

<img src=”/myapp/getMySecretImage.do”>

Type the image text here: <input type=”text” name=”thesecret”>

</form>

So, as you see above, the registration form has a image with an src that is pointing to a struts action. It could as well point to a JSP page or a CGI Script or whatever is capable of generating a image and returning.

Now, let us see what the image generation program looks like. Remember that it will not just return the image but also store the text that will display inside the image in user session.

So, if you are writing your struts action’s (/getMySecretImage) executre method will look like this (you can put the same thing in a servlet or JSP):

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;

import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics2D;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Iterator;

import javax.imageio.IIOImage;
import javax.imageio.ImageIO;
import javax.imageio.ImageWriteParam;
import javax.imageio.ImageWriter;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

public class MyCaptchaStrutsAction extends Action
{

public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request,
            HttpServletResponse response) throws Exception {
    
        String imageFormat = “jpg”;
      response.setContentType((new StringBuilder(“image/”)).append(imageFormat).toString());
         try
         {
             Color backgroundColor = Color.red;
             Color borderColor = Color.black;
             Color textColor = Color.white;
             Color circleColor = new Color(160, 160, 160);
             //Font textFont = new Font(“Arial”, 0, paramInt(request, “fontSize”, 24));
             Font textFont = new Font(“Arial”, 0, 24);
             int charsToPrint = 6;
             int width = 130; //paramInt(request, “width”, 130);
             int height = 40; //paramInt(request, “height”, 40);
             int circlesToDraw = 6;
             float horizMargin = 20F;
             float imageQuality = 0.95F;
             double rotationRange = 0.69999999999999996D;
             BufferedImage bufferedImage = new BufferedImage(width, height, 1);
             Graphics2D g = (Graphics2D)bufferedImage.getGraphics();
             g.setColor(backgroundColor);
             g.fillRect(0, 0, width, height);
             g.setColor(circleColor);
             for(int i = 0; i < circlesToDraw; i++)
             {
                 int circleRadius = (int)((Math.random() * (double)height) / 2D);
                 int circleX = (int)(Math.random() * (double)width – (double)circleRadius);
                 int circleY = (int)(Math.random() * (double)height – (double)circleRadius);
                 g.drawOval(circleX, circleY, circleRadius * 2, circleRadius * 2);
             }

             g.setColor(textColor);
             g.setFont(textFont);
             FontMetrics fontMetrics = g.getFontMetrics();
             int maxAdvance = fontMetrics.getMaxAdvance();
             int fontHeight = fontMetrics.getHeight();
             String elegibleChars = “ABCDEFGHJKLMPQRSTUVWXYabcdefhjkmnpqrstuvwxy23456789”;
             char chars[] = elegibleChars.toCharArray();
             float spaceForLetters = -horizMargin * 2.0F + (float)width;
             float spacePerChar = spaceForLetters / ((float)charsToPrint – 1.0F);
             g.getTransform();
             StringBuffer finalString = new StringBuffer();
             for(int i = 0; i < charsToPrint; i++)
             {
                 double randomValue = Math.random();
                 int randomIndex = (int)Math.round(randomValue * (double)(chars.length – 1));
                 char characterToShow = chars[randomIndex];
                 finalString.append(characterToShow);
                 //maxAdvance * 2;
                 //fontHeight * 2;
                 int charWidth = fontMetrics.charWidth(characterToShow);
                 int charDim = Math.max(maxAdvance, fontHeight);
                 int halfCharDim = charDim / 2;
                 BufferedImage charImage = new BufferedImage(charDim, charDim, 2);
                 Graphics2D charGraphics = charImage.createGraphics();
                 charGraphics.translate(halfCharDim, halfCharDim);
                 double angle = (Math.random() – 0.5D) * rotationRange;
                 charGraphics.transform(AffineTransform.getRotateInstance(angle));
                 charGraphics.translate(-halfCharDim, -halfCharDim);
                 charGraphics.setColor(textColor);
                 charGraphics.setFont(textFont);
                 int charX = (int)(0.5D * (double)charDim – 0.5D * (double)charWidth);
                 charGraphics.drawString((new StringBuilder()).append(characterToShow).toString(), charX, (charDim – fontMetrics.getAscent()) / 2 + fontMetrics.getAscent());
                 float x = (horizMargin + spacePerChar * (float)i) – (float)charDim / 2.0F;
                 int y = (height – charDim) / 2;
                 g.drawImage(charImage, (int)x, y, charDim, charDim, null, null);
                 charGraphics.dispose();
             }

             g.setColor(borderColor);
             g.drawRect(0, 0, width – 1, height – 1);
             Iterator iter = ImageIO.getImageWritersByFormatName(imageFormat);
             if(iter.hasNext())
             {
                 ImageWriter writer = (ImageWriter)iter.next();
                 ImageWriteParam iwp = writer.getDefaultWriteParam();
                 if(imageFormat.equalsIgnoreCase(“jpg”) || imageFormat.equalsIgnoreCase(“jpeg”))
                 {
                     iwp.setCompressionMode(2);
                     iwp.setCompressionQuality(imageQuality);
                 }
                 writer.setOutput(ImageIO.createImageOutputStream(response.getOutputStream()));
                 IIOImage imageIO = new IIOImage(bufferedImage, null, null);
                 writer.write(null, imageIO, iwp);
             } else
             {
                 throw new Exception(“No encoder found.”);
             }
             request.getSession().setAttribute(“CAPTCHA”, finalString.toString());
             g.dispose();
         }
         catch(Throwable e)
         {
          System.out.println(“Unable to build Captcha image: ” + e);
         }    
    
     return null;
    }

}

(NOTE: This image generation code in its JSP version is here. It has only been put in struts action form above.)

You will see that this line above:

request.getSession().setAttribute(“CAPTCHA”, finalString.toString());
stores the image text in session.

So, when the registration form is submitted, you can check against it.

 

 

 

 

Advertisements

One response

  1. Another Fantastic post, I will be sure to save this post in my Clipmarks account. Have a great day.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: