Integrate Free Anti-Bot Service reCAPTCHA with Spring MVC application
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
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.
Once signed up, two keys (Public key and Private key) will be provided for your domain.
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
7. Demo
Start the server and deploy the web application. Open the url http://:/ReCaptchaHelloWorld.
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".
For correct reCAPTCHA entry, you will be redirected to the success page.
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.