Using Google reCAPTCHA with Java Web Application

1- What is reCAPTCHA?

CAPTCHA is a validation tool on the website to ensure that your website is not SPAM by an automatic tool. Traditionally, captcha is an imagine with lines of text that an automated program is difficult to analyze, users must retype the text similar to the text on the picture to prove they are not a robot. The traditional CAPTCHA  can meet the requirements set out, however,  it's sometimes  quite annoying, the CAPTCHA inscription are sometimes  hard  for users to read.
Image of a traditional CAPTCHA:
reCAPTCHA is a free CAPTCHA service that helps protect your site against spam, malicious registrations and other forms of attacks where computers try to disguise themselves as a human. reCAPTCHA comes in the form of a widget that you can easily add to your blog, forum, registration, etc.
The illustration below describes the operating principles of reCAPTCHA:
  1. On data entry form containing Google reCAPTCHA.
  2. When users check the "I'm not a robot", an Ajax request will be automatically sent to Google reCAPTCHA service and receives an authentication code and it is hosted on a  Hidden field of form. All that users have to do is check on the "I'm not a robot" instead of having to read illegible inscription which is created by traditional CAPTCHA.
  3. After entering the information on the form and check the button "I'm not a robot", the user clicks the Submit form button.
  4. At the server, the program will create a request containing the authentication code in the previous step, send to Google reCAPTCHA service to verify the code. Google reCAPTCHA service will send back the verified results.

2- Preview Demo

3- Register Google reCAPTCHA

First you need to sign up for Google reCAPTCHA
After successful registration you have Site-Key & Secret-Key
  • Site Key: 6LelZAsTAAAAAAv1ADYDnq8AzbmPmbMvjh-xhfgB
  • Secret Key:  6LelZAsTAAAAAKa_s6g2yuJzByYlk0FH_6iTkZJC

4- Quick create example Project

  • File/New/Other..
Enter:
  • Group Id: org.o7planning
  • Artifact Id: reCaptchaDemo
  • package: org.o7planning.tutorial.recaptcha
Project was created.
Maven created webapp project which may be missing a few components, you need to fix it.
Web.xml configuration using WebApp 3.0 instead of  WebApp 2.3 which is automatically generated by Maven.
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app
    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_3_0.xsd"
    version="3.0">

 
  <display-name>Archetype Created Web Application</display-name>
 
</web-app>

 
Configuring Maven:
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>org.o7planning</groupId>
   <artifactId>reCaptchaDemo</artifactId>
   <packaging>war</packaging>
   <version>0.0.1-SNAPSHOT</version>
   <name>reCaptchaDemo Maven Webapp</name>
   <url>http://maven.apache.org</url>


   <dependencies>
       <dependency>
           <groupId>junit</groupId>
           <artifactId>junit</artifactId>
           <version>3.8.1</version>
           <scope>test</scope>
       </dependency>

       <!-- Servlet Library -->
       <!-- http://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
       <dependency>
           <groupId>javax.servlet</groupId>
           <artifactId>javax.servlet-api</artifactId>
           <version>3.1.0</version>
           <scope>provided</scope>
       </dependency>


       <!-- JSON Library -->
       <!-- http://mvnrepository.com/artifact/org.glassfish/javax.json -->
       <dependency>
           <groupId>org.glassfish</groupId>
           <artifactId>javax.json</artifactId>
           <version>1.0.4</version>
       </dependency>

   </dependencies>


 <build>
       <finalName>reCaptchaDemo</finalName>
       <plugins>
       
           <!-- Config: Maven Tomcat Plugin -->
           <!-- http://mvnrepository.com/artifact/org.apache.tomcat.maven/tomcat7-maven-plugin -->
           <plugin>
               <groupId>org.apache.tomcat.maven</groupId>
               <artifactId>tomcat7-maven-plugin</artifactId>
               <version>2.2</version>
               <!-- Config: contextPath and Port (Default - /reCaptchaDemo : 8080) -->
               <!--
               <configuration>
                   <path>/</path>
                   <port>8899</port>
               </configuration>
               -->    
           </plugin>
       </plugins>
   </build>

</project>
Now, your project has no error.

5- Code Project

This is an image after Project Completion:
MyConstants.java
package org.o7planning.tutorial.recaptcha;

public class MyConstants {

   
   public static final String SITE_KEY ="6LelZAsTAAAAAAv1ADYDnq8AzbmPmbMvjh-xhfgB";
   
   public static final String SECRET_KEY ="6LelZAsTAAAAAKa_s6g2yuJzByYlk0FH_6iTkZJC";
   
}
VerifyUtils.java
package org.o7planning.tutorial.recaptcha;

import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;

import javax.json.Json;
import javax.json.JsonObject;
import javax.json.JsonReader;
import javax.net.ssl.HttpsURLConnection;

public class VerifyUtils {

   public static final String SITE_VERIFY_URL = "https://www.google.com/recaptcha/api/siteverify";

   public static boolean verify( String gRecaptchaResponse) {
       if (gRecaptchaResponse == null || gRecaptchaResponse.length() == 0) {
           return false;
       }

       try {
           URL verifyUrl = new URL(SITE_VERIFY_URL);

           // Open Connection to URL
           HttpsURLConnection conn = (HttpsURLConnection) verifyUrl.openConnection();


           // Add Request Header
           conn.setRequestMethod("POST");
           conn.setRequestProperty("User-Agent", "Mozilla/5.0");
           conn.setRequestProperty("Accept-Language", "en-US,en;q=0.5");


           // Data will be sent to the server.
           String postParams = "secret=" + MyConstants.SECRET_KEY + "&response=" + gRecaptchaResponse;

           // Send Request
           conn.setDoOutput(true);
         
           // Get the output stream of Connection
           // Write data in this stream, which means to send data to Server.
           OutputStream outStream = conn.getOutputStream();
           outStream.write(postParams.getBytes());

           outStream.flush();
           outStream.close();

           // Response code return from server.
           int responseCode = conn.getResponseCode();
           System.out.println("responseCode=" + responseCode);


           // Get the InputStream from Connection to read data sent from the server.
           InputStream is = conn.getInputStream();

           JsonReader jsonReader = Json.createReader(is);
           JsonObject jsonObject = jsonReader.readObject();
           jsonReader.close();

           // ==> {"success": true}
           System.out.println("Response: " + jsonObject);

           boolean success = jsonObject.getBoolean("success");
           return success;
       } catch (Exception e) {
           e.printStackTrace();
           return false;
       }
   }
}
LoginServlet.java
package org.o7planning.tutorial.recaptcha.servlet;

import java.io.IOException;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet(urlPatterns = "/login")
public class LoginServlet extends HttpServlet {

  private static final long serialVersionUID = 958900029856081978L;

  @Override
  protected void doGet(HttpServletRequest req, HttpServletResponse resp)
          throws ServletException, IOException {
     
      RequestDispatcher dispatcher =
              req.getServletContext().getRequestDispatcher("/WEB-INF/views/loginView.jsp");
     
      dispatcher.forward(req, resp);

  }

  @Override
  protected void doPost(HttpServletRequest req, HttpServletResponse resp)
          throws ServletException, IOException {
      this.doGet(req, resp);
  }

}
DoLoginServlet.java
package org.o7planning.tutorial.recaptcha.servlet;

import java.io.IOException;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.o7planning.tutorial.recaptcha.VerifyUtils;

@WebServlet(urlPatterns = "/doLogin")
public class DoLoginServlet extends HttpServlet {

 private static final long serialVersionUID = 958900029856081978L;

 @Override
 protected void doGet(HttpServletRequest request, HttpServletResponse response)
         throws ServletException, IOException {

     String userName = request.getParameter("userName");
     String password = request.getParameter("password");

     boolean valid = true;
     String errorString = null;

     // Check userName & password
     if (!"tom".equals(userName) || !"tom001".equals(password)) {
         valid = false;
         errorString = "UserName or Password invalid!";
     }

     if (valid) {

         String gRecaptchaResponse = request.getParameter("g-recaptcha-response");

         System.out.println("gRecaptchaResponse=" + gRecaptchaResponse);

         // Verify CAPTCHA.
         valid = VerifyUtils.verify(gRecaptchaResponse);
         if (!valid) {
             errorString = "Captcha invalid!";
         }
     }
     if (!valid) {
         request.setAttribute("errorString", errorString);
         RequestDispatcher dispatcher = //
                     request.getServletContext().getRequestDispatcher("/WEB-INF/views/loginView.jsp");
       
         dispatcher.forward(request, response);
         return;
     } else {
         request.getSession().setAttribute("loginedUser", userName);
         // Redirect to /userInfo
         response.sendRedirect(request.getContextPath()+"/userInfo");
     }
 }

 @Override
 protected void doPost(HttpServletRequest req, HttpServletResponse resp)
                                           throws ServletException, IOException {
     this.doGet(req, resp);
 }

}
UserInfoServlet.java
package org.o7planning.tutorial.recaptcha.servlet;

import java.io.IOException;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet(urlPatterns = "/userInfo")
public class UserInfoServlet extends HttpServlet {

  private static final long serialVersionUID = 958900029856081978L;

  @Override
  protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
      if (req.getSession().getAttribute("loginedUser") == null) {
          resp.sendRedirect(req.getContextPath() + "/login");
          return;
      }

      RequestDispatcher dispatcher = req.getServletContext().getRequestDispatcher("/WEB-INF/views/userInfoView.jsp");

      dispatcher.forward(req, resp);

  }

  @Override
  protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
      this.doGet(req, resp);
  }

}
You need to declare the javascript library to use reCAPTCHA on JSP pages. Note that reCAPTCHA supports 40 user languages. You can configure specific language to display on  reCAPTCHA or by default, in case of default,  reCAPTCHA will display the language according to the geographical location of the user (based on IP addresses).
<!-- reCAPTCHA with English language -->
<script src='https://www.google.com/recaptcha/api.js?hl=en'></script>


<!-- reCAPTCHA with Vietnamese language -->
<script src='https://www.google.com/recaptcha/api.js?hl=vi'></script>


<!-- reCAPTCHA with Auto language -->
<script src='https://www.google.com/recaptcha/api.js'></script>
/WEB-INF/views/loginView.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
  pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Login</title>

<!-- reCAPTCHA Libary -->
<script src='https://www.google.com/recaptcha/api.js?hl=en'></script>

</head>
<body>

 <h3>Login:</h3>
 
 <p style="color:red;">${errorString}</p>

  <form name="loginForm" method="POST" action="doLogin">
      <table border="0">
          <tr>
              <td>User Name</td>
              <td><input type="text" name="userName" /></td>
          </tr>
          <tr>
              <td>Password</td>
              <td><input type="password" name="password" /></td>
          </tr>
      </table>
     
      <!-- reCAPTCHA -->
      <div class="g-recaptcha"
          data-sitekey="6LelZAsTAAAAAAv1ADYDnq8AzbmPmbMvjh-xhfgB"></div>

      <input type="submit" value="Submit" />

  </form>
  <p style="color:blue;">User Name: tom, Password: tom001</p>

</body>
</html>
/WEB-INF/views/userInfoView.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
  pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<title>User Info</title>


</head>
<body>

 Hello ${loginedUser}

</body>
</html>

6- Configure and run Project

Enter:
  • Name: Run reCaptchaDemo
  • Base directory: ${workspace_loc:/reCaptchaDemo}
  • Goals: tomcat7:run
Run URL: