CAPTCHA Randomization Java Code Example

The Java Captcha Randomization code example shows how to easily randomize various BotDetect Java Captcha parameters, beyond the basic image and sound style randomization used by default.

First Time Here?

Check the BotDetect JSP Captcha Quickstart for key integration steps.

Randomly using different Captcha image algorithms and other parameter values (such as code length and style) can significantly improve the Captcha security.

This is the recommended approach to Captcha property setting, since it takes full advantage of the 60 Captcha image generation algorithms shipped with BotDetect, as well as built-in randomization features..

To randomize Captcha for every request we will use custom javax.servlet.Filter.

Downloaded Location

The CAPTCHA Randomization Java Example is included in examples folder of the download package as bdc3-captcha-randomization-example.war file. Deploying (unpacking) the file will create a standard JSP directory tree.

index.jsp

<%@page contentType="text/html" pageEncoding="UTF-8"%>
<%@page import="botdetect.web.Captcha"%>
<!DOCTYPE html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>BotDetect CAPTCHA Randomization Example</title>
    <link rel="stylesheet" href="stylesheet.css" type="text/css"/>
  </head>
  <body>
    <form action="index.jsp" method="post">
      <h1>BotDetect CAPTCHA Randomization Example</h1>
      <fieldset>
        <legend>CAPTCHA Validation</legend>
        <label for="captchaCodeTextBox" class="prompt">
            Retype the code from the picture:</label>
        <%
        // Adding BotDetect Captcha to the page
        Captcha captcha = Captcha.load(request, "randomizedCaptcha");
        captcha.renderCaptchaMarkup(pageContext.getServletContext(), 
            pageContext.getOut());
        %>
        <div class="validationDiv">
          <input id="captchaCodeTextBox" type="text" 
              name="captchaCodeTextBox" />
          <input type="submit" name="validate" value="Validate" />&nbsp;
          <%
          if("POST".equalsIgnoreCase(request.getMethod())){
            // validate the Captcha to check we're not dealing with a bot
            boolean isHuman = captcha.validate(request, 
                request.getParameter("captchaCodeTextBox"));
            if (isHuman) {
              // Captcha validation passed, perform protected action
              out.print("<span class=\"correct\">Correct.</span>");
            } else {
              // Captcha validation failed, show error message
              out.print("<span class=\"incorrect\">Incorrect!</span>");
            }
          }
          %>
        </div>
      </fieldset>
    </form>
  </body>
</html>

In the form source, we follow the standard procedure for adding Captcha protection to a JSP form.

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
     http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
  <session-config>
    <session-timeout>
      30
    </session-timeout>
  </session-config>
  <servlet>
    <servlet-name>BotDetect Captcha</servlet-name>
    <servlet-class>botdetect.web.http.CaptchaServlet</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>BotDetect Captcha</servlet-name>
    <url-pattern>/botdetectcaptcha</url-pattern>
  </servlet-mapping>
  <context-param>
    <param-name>LBD_helpLinkMode</param-name>
    <param-value>image</param-value>
  </context-param>
  <filter>
    <filter-name>captchaFilter</filter-name>
    <filter-class>
      botdetect.examples.jsp.randomization.filter.CaptchaFilter
    </filter-class>
  </filter>
  <filter-mapping>
    <filter-name>captchaFilter</filter-name>
    <servlet-name>BotDetect Captcha</servlet-name>
  </filter-mapping>
  <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>
</web-app>

In WEB-INF/web.xml file we declare custom filter and map it to BotDetect Captcha servlet in order to randomize Captcha appearance for every Captcha generation request.

CaptchaFilter.java

package botdetect.examples.jsp.randomization.filter;

import botdetect.CaptchaHttpCommand;
import botdetect.CodeStyle;
import botdetect.ImageStyle;
import botdetect.support.CaptchaRandomization;
import botdetect.web.Captcha;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;


public class CaptchaFilter implements Filter{

  public void init(FilterConfig filterConfig) throws ServletException {}

  public void doFilter(ServletRequest request, ServletResponse response, 
      FilterChain chain) throws IOException, ServletException {
    if(CaptchaHttpCommand.getCaptchaCommand((HttpServletRequest)request) ==
        CaptchaHttpCommand.GET_IMAGE){
      Captcha captcha = Captcha.load(request);

      captcha.setCodeLength(CaptchaRandomization.getRandomCodeLength(2, 4));

      // Captcha code style randomization, 
      // option 1: randomly use all possible code styles
//      captcha.setCodeStyle(CaptchaRandomization.getRandomCodeStyle());

      // Captcha code style randomization, 
      // option 2: randomly choose from the given set of code styles
//      CodeStyle[] codeStyles = {
//        CodeStyle.ALPHA,
//        CodeStyle.NUMERIC
//      };
//      captcha.setCodeStyle(CaptchaRandomization.
//          getRandomCodeStyle(codeStyles));

      // Captcha code style randomization, 
      // option 3: dependent on code length
      switch(captcha.getCodeLength()){
        case 2:
          captcha.setCodeStyle(CodeStyle.ALPHA);
          break;
        case 3:
          captcha.setCodeStyle(CodeStyle.ALPHANUMERIC);
          break;
        case 4:
          captcha.setCodeStyle(CodeStyle.NUMERIC);
          break;
      }

      //use an image style randomly selected from the given subset
      List<ImageStyle> imageStyles = new ArrayList<ImageStyle>();
      imageStyles.add(ImageStyle.BlackOverlap);
      imageStyles.add(ImageStyle.Bubbles);
      imageStyles.add(ImageStyle.Bullets);
      imageStyles.add(ImageStyle.Bullets2);

      captcha.setImageStyle(CaptchaRandomization.
          getRandomImageStyle(imageStyles));

      request.setAttribute(captcha.getCaptchaId(), captcha);
    }

    chain.doFilter(request, response);
  }

  public void destroy() {}

}

In most cases, randomization of Captcha settings can be achieved using the CaptchaRandomization helper included in the Captcha library. Commented-out code shows different randomization options available - calling a randomization method without any parameters returns a value randomly selected among all possible values, while passing an array of user-defined options will restrict the randomization to only the included values.

Randomization settings can be customized to suit each individual use case; BotDetect will automatically randomize the Captcha image style by default, but other options are available. In the example, we randomly use Captcha images containing either 2 alpha characters, 3 alphanumeric characters, or 4 numeric ones.

Please Note

BotDetect Java Captcha Library v4.0.Beta3 is an in-progress port of BotDetect 4 Captcha, and we need you to guide our efforts towards a polished product. Please let us know if you encounter any bugs, implementation issues, or a usage scenario you would like to discuss.