Hướng dẫn sử dụng Google reCAPTCHA trong ứng dụng Web Java
Công ty Vĩnh Cửu tuyển dụng lập trình viên Java

1- reCAPTCHA là gì

CAPTCHA là một công cụ xác thực trên website để đảm bảo rằng website của bạn không bị SPAM bằng một công cụ tự động. Theo truyền thống captcha là một hình ảnh với dòng các chữ khó phân tích bởi một chương trình tự động, người dùng phải nhập lại dòng chữ giống với chữ trên hình ảnh để chứng minh họ không phải là cái máy. CAPTCHA truyền thống có thể đáp ứng được yêu cầu đặt ra tuy nhiên đôi khi khá phiền phức, các dòng chữ CAPTCHA đôi khi rất khó đọc đối với người dùng.
Hình ảnh một CAPTCHA truyền thống:
reCAPTCHA là một dịch vụ CAPTCHA miễn phí giúp website của bạn chống lại SPAM, các đăng ký độc hại, hoặc các hình thức tấn công khác, nơi mà các chương trình tấn công cố gắng che giấu bản thân tạo ra các hành vi giống con người. reCAPTCHA với giao diện đơn giản, có thể dễ dàng thêm vào blog, forum hoặc website của bạn,...
Hình minh họa dưới đây mô tả nguyên tắc hoạt động của reCAPTCHA:
  1. Trên form nhập dữ liệu, có chứa Google reCAPTCHA.
  2. Khi người dùng check vào "I'm not a robot", một Ajax request sẽ tự động gửi tới Google reCAPTCHA service và nhận được một mã số xác thực nó được lưu trữ trên một Hidden field (g-recaptcha-response) của form. Tất cả những gì người dùng phải làm là check vào nút "I'm not a robot" thay vì phải đọc một dòng chữ khó đọc được tạo ra bởi CAPTCHA truyền thống.
  3. Người dùng nhấn nút Submit form, Server sẽ sử lý dữ liệu người dùng gửi tới, tại đây chương trình sẽ tạo một request có chứa thông tin mã xác thực ở bước trên để gửi tới dịch vụ Google reCAPTCHA để kiểm chứng lại mã. Dịch vụ Google reCAPTCHA sẽ gửi lại kết quả xác minh.

2- Xem trước Demo

3- Đăng ký Google reCAPTCHA

Trước hết bạn cần phải đăng ký Google reCAPTCHA
Sau khi đăng ký thành công bạn có Site-Key & Secret-Key
  • Site Key: 6LelZAsTAAAAAAv1ADYDnq8AzbmPmbMvjh-xhfgB
  • Secret Key:  6LelZAsTAAAAAKa_s6g2yuJzByYlk0FH_6iTkZJC

4- Tạo Nhanh Project để làm ví dụ

  • File/New/Other..
Nhập vào:
  • Group Id: org.o7planning
  • Artifact Id: reCaptchaDemo
  • package: org.o7planning.tutorial.recaptcha
Project đã được tạo ra.
Maven tạo ra webapp project có thể thiếu một vài thành phần, bạn cần fix nó.
Cấu hình web.xml sử dụng WebApp 3.0 thay vì WebApp 2.3 vốn được tự động tạo ra bởi 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>

 
Cấu hình 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>
Project của bạn đã không còn thông báo lỗi.

5- Code Project

Đây là hình ảnh Project sau khi hoàn thành:
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);

           // Mở kết nối (Connection) tới URL trên.
           HttpsURLConnection conn = (HttpsURLConnection) verifyUrl.openConnection();

           // Thêm các thông tin Header vào Request chuẩn bị gửi tới server.
           // Add Request Header
           conn.setRequestMethod("POST");
           conn.setRequestProperty("User-Agent", "Mozilla/5.0");
           conn.setRequestProperty("Accept-Language", "en-US,en;q=0.5");

           // Dữ liệu sẽ gửi tới server.
           String postParams = "secret=" + MyConstants.SECRET_KEY + "&response=" + gRecaptchaResponse;

           // Send Request
           conn.setDoOutput(true);

           // Lấy luồng đầu ra của kết nối tới server.
           // Ghi dữ liệu vào luồng này, có nghĩa là gửi thông tin đến Server.
           OutputStream outStream = conn.getOutputStream();
           outStream.write(postParams.getBytes());

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

           // Mã trả lời trả về từ Server.
           int responseCode = conn.getResponseCode();
           System.out.println("responseCode=" + responseCode);

           // Lấy InputStream từ Connection để đọc dữ liệu gửi về từ 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);
  }

}
Để sử dụng reCAPTCHA trên trang JSP bạn cần khai báo thư viện javascript. Chú ý rằng reCAPTCHA hỗ trợ 40 ngôn ngữ người dùng. Bạn có thể cấu hình cụ thể ngôn ngữ hiển thị trên reCAPTCHA hoặc để mặc định, trong trường hợp mặc định reCAPTCHA sẽ hiển thị ngôn ngữ theo vị trí địa lý của người dùng (Dựa trên địa chỉ 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- Cấu hình và chạy Project

Nhập vào:
  • Name: Run reCaptchaDemo
  • Base directory: ${workspace_loc:/reCaptchaDemo}
  • Goals: tomcat7:run
Bạn có thể chạy URL: