reCAPTCHA is a free CAPTCHA service to protect a site against spam and other types of automated abuse by bots or computer programs. reCAPTCHA provides widget which can easily be integrated to your blog, forum, comment, registration form, contact form, etc and you can be rest assured that only human is posting in your site.

This post will guide you on how to integrate free anti-bot service reCAPTCHA with a Spring MVC application.

Tools and Technologies used in this article

  1. reCAPTCHA
  2. Spring Framework 3.2
  3. Spring Tool Suite 3.2
  4. JDK 1.6
  5. Tomcat 7

Note : Spring 3 requires at least JDK 5. So, make sure you have JDK 5 or above.

1. Sign up for reCAPTCHA API keys

Use your existing google account or open a new one to sign up for reCAPTCHA API keys for your site. Provide domain name (say www.yoursite.com) and click 'Create Key' button.
Create a reCAPTCHA key

Once signed up, two keys (Public key and Private key) will be provided for your domain.
reCAPTCHA Public and Private key

Note:
By default, all reCAPTCHA keys work for 'localhost' / '127.0.0.1' in local development or test environment. As the name itself suggests, be sure to keep Private key as secret.

Integration of reCAPTCHA into a form, mainly consists of following two steps
a. Client side code to display reCAPTCHA widget.
b. Server side code to verify user's answer by connecting to reCAPTCHA server.

2. Add reCAPTCHA Maven dependency

Add reCAPTCHA Maven dependency along with servlet-api in pom.xml.
File : pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.srccodes.spring</groupId>
    <artifactId>spring-mvc-recaptcha-hello</artifactId>
    <packaging>war</packaging>
    <version>0.0.1-SNAPSHOT</version>
    <name>spring-mvc-recaptcha-hello Maven Webapp</name>
    <url>http://maven.apache.org</url>
    <properties>
        <spring-webmvc-version>3.2.3.RELEASE</spring-webmvc-version>
        <recaptcha4j-version>0.0.7</recaptcha4j-version>
    </properties>
 
    <dependencies>
        <!-- Spring MVC depends on spring-core, spring-beans, spring-context, spring-web -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>${spring-webmvc-version}</version>
        </dependency>
 
        <!-- reCaptcha -->
        <dependency>
            <groupId>net.tanesha.recaptcha4j</groupId>
            <artifactId>recaptcha4j</artifactId>
            <version>${recaptcha4j-version}</version>
        </dependency>
 
        <!-- Servlet -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>servlet-api</artifactId>
            <version>2.5</version>
            <scope>provided</scope>
        </dependency>
    </dependencies>
 
    <build>
        <finalName>ReCaptchaHelloWorld</finalName>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>2.5.1</version>
                <configuration>
                    <source>1.6</source>
                    <target>1.6</target>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

3. Client side code to display reCAPTCHA widget

We'll encapsulate all the codes to generate reCAPTCHA widget in a tagfile (say captcha.tag) so that it can be reused in other forms as well in the application.
File : WEB-INF/tags/captcha.tag

<%@ tag import="net.tanesha.recaptcha.ReCaptcha" %>
<%@ tag import="net.tanesha.recaptcha.ReCaptchaFactory" %>
 
<script type="text/javascript">var RecaptchaOptions = {theme : 'clean'};</script> 
<%
    ReCaptcha reCaptcha = ReCaptchaFactory.newReCaptcha("[your reCaptcha public key]", "[your reCaptcha private key]", false);
    out.print(reCaptcha.createRecaptchaHtml(null, null));
%>

Note:
Do not forget to replace "[your reCaptcha public key]" and "[your reCaptcha private key]" with your actual public and private API key. createRecaptchaHtml(String errorMessage, Properties options) creates HTML code with embedded recaptcha.

Now use this tagfile (e.g. sc:captcha) in your form to display reCAPTCHA widget.
File: WEB-INF/pages/captcha.jsp

<%@ taglib tagdir='/WEB-INF/tags' prefix='sc'%>
<html>
<head>
    <title>Captcha Entry Form</title>
</head>
<body>
Are you human? <font color="red">${message}</font>
<br/>
<form action="/ReCaptchaHelloWorld/recaptcha" method="post"> 
    <sc:captcha/>
    <input type="submit" value="submit"/> 
</form>
</body>
</html>

4. Add reCAPTCHA bean

Add bean definition of reCAPTCHA implementation in spring configuration xml. Using annotation @Autowire, this bean is injected into controller.
File: WEB-INF/dispatcher-servlet.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:p="http://www.springframework.org/schema/p"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd 
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd 
    http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd">
 
    <context:component-scan base-package="com.srccodes.spring.controller" />
    <mvc:annotation-driven />
     
    <bean id="reCaptchaService" class="net.tanesha.recaptcha.ReCaptchaImpl">
        <property name="privateKey" value="[your reCaptcha private key]"></property>
    </bean>
     
    <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/pages/" />
        <property name="suffix" value=".jsp" />
    </bean>
</beans>

Note: Do not forget to replace "[your reCaptcha private key]" with your actual API private key.

5. Server side code to verify user's entry

Now we'll write one controller class (say ReCaptchaHelloWorldController) with a handler method to verify reCAPTCHA words entered by the user.
File : com/srccodes/spring/controller/ReCaptchaHelloWorldController.java

package com.srccodes.spring.controller;
 
import javax.servlet.ServletRequest;
 
import net.tanesha.recaptcha.ReCaptcha;
import net.tanesha.recaptcha.ReCaptchaResponse;
 
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.ServletRequestUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
 
/**
 * @author Abhijit Ghosh
 * @version 1.0
 */
@Controller
public class ReCaptchaHelloWorldController {
    @Autowired
    private ReCaptcha reCaptchaService = null;
     
     
    @RequestMapping(value={"/", "/recaptcha"},  method=RequestMethod.GET)
    public String show() {  
        return "captcha";
    }
     
    @RequestMapping(value="/recaptcha", method=RequestMethod.POST)
    public String verify(ServletRequest request, Model model) { 
        String challenge = request.getParameter("recaptcha_challenge_field");
        String response = request.getParameter("recaptcha_response_field");
        String remoteAddr = request.getRemoteAddr();
         
        ReCaptchaResponse reCaptchaResponse = reCaptchaService.checkAnswer(remoteAddr, challenge, response);
         
        if(reCaptchaResponse.isValid()) {
            model.addAttribute("message", "reCaptcha Hello World!");
            return "success";
        } else {
            model.addAttribute("message", "Try again and prove it.");
            return "captcha";
        }
    }
 
}

User will be redirected to either initial page (captcha.jsp) having reCAPTCHA widget or success page (success.jsp) based on the ReCaptchaResponse received from the reCAPTCHA sever.
File: WEB-INF/pages/success.jsp

<html>
<body>
<h2>${message}</h2>
</body>
</html>

6. Overall Project Structure

Overall Project Structure

7. Demo

Start the server and deploy the web application. Open the url http://:/ReCaptchaHelloWorld.
reCAPTCHA widget

If you enter wrong words and submit the form, then you will be redirected to the same page with an error message "Try again and prove it".
reCAPTCHA challenge failed

For correct reCAPTCHA entry, you will be redirected to the success page.
reCAPTCHA challenge passed

8. Live Demo

To experience the live demo, please browse JavaScript Extractor Tool.

Download SrcCodes

All code samples shown in this post are available on GitHub.

References