Использование Google reCAPTCHA с веб-приложением Java

1- Что такое reCAPTCHA

CAPTCHA, является инструментом подтверждения на Website, чтобы удостовериться, что ваш Website не будет получать  SPAM из автоматического инструмента. Традиционно captcha является изображением с буквами, которые трудно разобрать используя автоматические программы, пользователь должен вводить слова которые видит на картинке, чтобы доказать, что он не являются машиной. Традиционный CAPTCHA, может соответствовать требованиям, но иногда бывают сложности, надпись CAPTCHA, иногда очень трудно читается пользователями.
Изображение традиционноо CAPTCHA:
reCAPTCHA  является бесплатной услугой  CAPTCHA, которая помогает вашему Website защищаться от SPAM, вредных регистраций или других форм атак, когда программы злоумышленники пытаются создать действия похожие на действия людей. reCAPTCHA с простым интерфейсом, можно легко добавить в ваш блог, форум или веб-сайт, ...
Изрбражение ниже описывает принцип работы reCAPTCHA:
  1. На форме ввода данных, содержится Google reCAPTCHA.
  2. Когда пользователи нажимает на "I'm not a robot", Ajax request автоматическо отправляет услуге Google reCAPTCHA и получает код аутентификации, который хранится на hidden file (g-Recaptcha-response) формы. Все, что пользователи должны сделать, это нажать на кнопку "I'm not a robot", вместо того, чтобы читать трудный текст, который создается традиционным CAPTCHA.
  3. Пользователи нажимают кнопку Submit form, Server будет обрабатывать данные,которые отправляют пользователи, программа создаст request, содержащий код аутентификации как в шаге выше, чтобы отправить услуге Google reCAPTCHA и проверить код. Услуга Google reCAPTCHA отправляет обратно результаты для подтверждения.

2- Предварительно просмотреть Demo

3- Регистрация Google reCAPTCHA

Прежде всего, необходимо зарегистрироваться для  Google reCAPTCHA
После успешной регистрации, у вас есть Site-Key & Secret-Key
  • Site Key: 6LelZAsTAAAAAAv1ADYDnq8AzbmPmbMvjh-xhfgB
  • Secret Key:  6LelZAsTAAAAAKa_s6g2yuJzByYlk0FH_6iTkZJC

4- Быстро создать Project чтобы сделать пример

  • File/New/Other..
Введите:
  • Group Id: org.o7planning
  • Artifact Id: reCaptchaDemo
  • package: org.o7planning.tutorial.recaptcha
Проект создан.
Maven создавает  Webapp project у которого может не хватать нескольких компонентов,  вам нужно исправить его.
Web.xml конфигурация использует WebApp 3.0 вместо WebApp2.3, который автоматически генерируется с помощью  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>

 
Конфигурация 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>
Ваш проект больше не сообщает об ошибке.

5- Code Project

Это изображение проекта после завершения:
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);
  }

}
Чтобы использовать reCAPTCHA на странице JSP вам нужно объявить библиотеку javascript. Заметьте, что  reCAPTCHA поддерживает 40 языков пользователей. Вы можете настроить оперделенный язык отображенный на reCAPTCHA или оставить по умолчанию, если по умолчанию, то  reCAPTCHA отображает язык по географическому местоположению пользователя (на основе IP-адреса).
<!-- 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- Конфигурация и запуск Project

Введите:
  • Name: Run reCaptchaDemo
  • Base directory: ${workspace_loc:/reCaptchaDemo}
  • Goals: tomcat7:run
Вы можете запустить URL: