Creating Captcha using Java

 


In this tutorial we will see how to create Captcha using Java code and to validate through JSP. In recent days we will be seeing in most of the websites are using Captcha for security and to reduce spam entries to their website. 
Captcha is nothing but displaying text, numbers or symbols combination as an image which can not traced automatically by computers, only human can identify. In online there are lot built-in Captcha are available which can be directly included in our sites. Some will be better than other sites like it included text, voice etc.,

Here lets see simple Java code to create Captcha and to test with web application using JSP. Below are the list of files which we are going to use in this demo. 

CaptchaImage.java is a class which will generate random Captcha BufferedImage.

index.jsp used to display Captcha image and to test



CaptchaImage.java


import java.awt.*;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;

public class CaptchaImage {

    String captchaString = "";

    // Function to generate random captcha image and returns the BufferedImage
    public BufferedImage getCaptchaImage() {
        try {
            Color backgroundColor = Color.white;
            Color borderColor = Color.black;
            Color textColor = Color.black;
            Color circleColor = new Color(190, 160, 150);
            Font textFont = new Font("Verdana", Font.BOLD, 20);
            int charsToPrint = 6;
            int width = 160;
            int height = 50;
            int circlesToDraw = 25;
            float horizMargin = 10.0f;
            double rotationRange = 0.7; 
            BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
            Graphics2D g = (Graphics2D) bufferedImage.getGraphics();
            g.setColor(backgroundColor);
            g.fillRect(0, 0, width, height);

            // lets make some noisey circles
            g.setColor(circleColor);
            for (int i = 0; i < circlesToDraw; i++) {
                int L = (int) (Math.random() * height / 2.0);
                int X = (int) (Math.random() * width - L);
                int Y = (int) (Math.random() * height - L);
                g.draw3DRect(X, Y, L * 2, L * 2, true);
            }
            g.setColor(textColor);
            g.setFont(textFont);
            FontMetrics fontMetrics = g.getFontMetrics();
            int maxAdvance = fontMetrics.getMaxAdvance();
            int fontHeight = fontMetrics.getHeight();

            // i removed 1 and l and i because there are confusing to users...
            // Z, z, and N also get confusing when rotated
            // this should ideally be done for every language...
            // 0, O and o removed because there are confusing to users...
            // i like controlling the characters though because it helps prevent confusion
            String elegibleChars = "ABCDEFGHJKLMNPQRSTUVWXYabcdefghjkmnpqrstuvwxy23456789";
            char[] chars = elegibleChars.toCharArray();
            float spaceForLetters = -horizMargin * 2 + width;
            float spacePerChar = spaceForLetters / (charsToPrint - 1.0f);
            StringBuffer finalString = new StringBuffer();
            for (int i = 0; i < charsToPrint; i++) {
                double randomValue = Math.random();
                int randomIndex = (int) Math.round(randomValue * (chars.length - 1));
                char characterToShow = chars[randomIndex];
                finalString.append(characterToShow);

                // this is a separate canvas used for the character so that
                // we can rotate it independently
                int charWidth = fontMetrics.charWidth(characterToShow);
                int charDim = Math.max(maxAdvance, fontHeight);
                int halfCharDim = (int) (charDim / 2);
                BufferedImage charImage = new BufferedImage(charDim, charDim, BufferedImage.TYPE_INT_ARGB);
                Graphics2D charGraphics = charImage.createGraphics();
                charGraphics.translate(halfCharDim, halfCharDim);
                double angle = (Math.random() - 0.5) * rotationRange;
                charGraphics.transform(AffineTransform.getRotateInstance(angle));
                charGraphics.translate(-halfCharDim, -halfCharDim);
                charGraphics.setColor(textColor);
                charGraphics.setFont(textFont);
                int charX = (int) (0.5 * charDim - 0.5 * charWidth);
                charGraphics.drawString("" + characterToShow, charX, (int) ((charDim - fontMetrics.getAscent()) / 2 + fontMetrics.getAscent()));
                float x = horizMargin + spacePerChar * (i) - charDim / 2.0f;
                int y = (int) ((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);
            g.dispose();
            captchaString = finalString.toString();
            System.out.println(captchaString);
            return bufferedImage;
        } catch (Exception ioe) {
            throw new RuntimeException("Unable to build image", ioe);
        }
    }

    // Function to return the Captcha string
    public String getCaptchaString() {
        return captchaString;
    }
}


index.jsp


<%@page import="javax.imageio.ImageIO"%>
<%@page import="java.io.File"%>
<%@page import="java.awt.image.BufferedImage"%>
<%@page import="com.test.CaptchaImage"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>My Captcha</title>
</head>
<body>

<%
 String result = "Invalid Entry.... :(";
 String color = "red";
    if(request.getParameter("captcha") != null && session.getAttribute("captchaStr") != null){
  if(session.getAttribute("captchaStr").equals(request.getParameter("captcha"))){
   result = "Valid Entry.... :)";
   color = "green";
  }
 }

 CaptchaImage obj = new CaptchaImage();
 BufferedImage ima = obj.getCaptchaImage();
 File outputfile = new File("c://image.jpg");
 ImageIO.write(ima, "jpg", outputfile);
 String captchaStr = obj.getCaptchaString();
 
 session.setAttribute("captchaStr", captchaStr);

%>


<form action="index.jsp" method="post">
 <table>
  <tr>
   <td><img alt="Captcha" src="c://image.jpg"/> </td>
  </tr>
  <tr>
   <td> <input type="text" value="" name="captcha"> </td>
  </tr>
  <tr>
   <td> <input type="submit" value="Submit"> </td>
  </tr>
  <tr>
   <td> <font color="<%=color%>">Value : <%= result %></font></td>
  </tr>
 </table>
</form>

</body>
</html>


OUTPUT:

Creating Captcha using Java





Creating Captcha using Java




9 comments:
Write comments