Tôi chưa bao giờ thích Captcha vì chúng luôn đặt gánh nặng lên người dùng, buộc họ phải đọc hiểu các ký tự và chứng minh rằng mình là con người chứ không phải một chương trình tự động. Nhưng gần đây, khi tôi thấy Google reCAPTCHA mới trên một trang web, tôi đã ngay lập tức thích nó.

Đơn giản vì tất cả những gì chúng ta cần làm chỉ là đánh dấu vào một ô và hệ thống sẽ tự động xác định bạn là người hay robot. Google gọi đây là “Trải nghiệm reCAPTCHA không CAPTCHA” và công nghệ này sử dụng một công cụ phân tích rủi ro tiên tiến cùng với các CAPTCHA thích ứng để ngăn chặn phần mềm tự động thực hiện các hành vi lạm dụng trên trang web của bạn.

Và đó cũng chính là lý do tôi viết bài này, để hướng dẫn bạn cách tích hợp Google reCAPTCHA vào ứng dụng web Java của mình. Trước khi bắt dự án, việc đầu tiên bạn cần làm là truy cập Google reCAPTCHA và đăng ký. Sau khi đăng ký, bạn sẽ nhận được một Site key dùng để hiển thị widget reCaptcha trên các trang web của bạn. Bạn cũng sẽ nhận được một Secret key mà bạn cần giữ bí mật và sử dụng để gửi yêu cầu xác thực với Google nhằm xác minh phản hồi captcha.
Sau khi tôi đăng ký một trang web thử nghiệm, tôi đã nhận được các khóa dưới đây và sẽ sử dụng chúng trong dự án của mình.
Lưu ý: Khi đăng ký, bạn cũng cần cung cấp tên miền và các khóa sẽ chỉ hoạt động trên tên miền đó. Ngoài ra, các khóa sẽ luôn hoạt động trên localhost, vì vậy tôi có thể dễ dàng kiểm thử nó trên máy chủ cục bộ của mình.

Bây giờ chúng ta có thể chuyển sang dự án ví dụ của mình. Chúng ta sẽ có một trang đăng nhập nơi người dùng nhập tên người dùng và mật khẩu, ngoài ra họ cũng sẽ phải giải reCaptcha và gửi form. Sau khi form được gửi, tên người dùng và mật khẩu sẽ được xác thực trong ứng dụng của chúng ta, trong khi đó chúng ta sẽ gửi phản hồi captcha cùng với secret key đến máy chủ Google reCaptcha và nhận phản hồi. Phản hồi từ Google reCaptcha là một JSON với một trường boolean success, nếu được xác thực thành công thì giá trị sẽ là true nếu không sẽ là false. Tôi sẽ sử dụng Java JSON Processing API để phân tích cú pháp response JSON. Hình ảnh dưới đây cho thấy dự án cuối cùng của chúng ta trong Eclipse.

Để có được khung sườn dự án, bạn chỉ cần tạo một “Dynamic Web Project” trong Eclipse và sau đó chuyển đổi nó thành dự án Maven. Chỉ cần thêm dependency dưới đây vào tệp pom.xml cho JSON API.
<dependency>
<groupId>org.glassfish</groupId>
<artifactId>javax.json</artifactId>
<version>1.0.2</version>
</dependency>
Hãy cùng xem xét từng thành phần một.
Trang View với Google reCAPTCHA
Dưới đây là mã trang HTML đăng nhập của chúng ta: login.html
<!DOCTYPE html>
<html>
<head>
<meta charset="US-ASCII">
<title>Login Page</title>
<script src="<https://www.google.com/recaptcha/api.js>"></script>
</head>
<body>
<form action="LoginServlet" method="post">
Username: <input type="text" name="user"> <br> Password:
<input type="password" name="pwd"> <br>
<div class="g-recaptcha"
data-sitekey="6LdMAgMTAAAAAGYY5PEQeW7b3L3tqACmUcU6alQf"></div>
<br> <input type="submit" value="Login">
</form>
</body>
</html>
Chúng ta cần thêm tệp JS của Google reCaptcha vào phần HTML head section và sau đó thêm <div class="g-recaptcha" data-sitekey="Site-key"></div> vào form của chúng ta để có được tiện ích reCaptcha. Đó là tất cả ở phía client, thực sự rất đơn giản! Sau khi người dùng được xác thực, họ sẽ được chuyển đến trang thành công dưới đây. LoginSuccess.jsp
<%@ page language="java" contentType="text/html; charset=US-ASCII"
pageEncoding="US-ASCII"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "<https://www.w3.org/TR/html4/loose.dtd>">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
<title>Login Success Page</title>
</head>
<body>
<h3>Hi Pankaj, Login successful.</h3>
<a href="login.html">Login Page</a>
</body>
</html>
Login Servlet
Dưới đây là mã LoginServlet.java đơn giản, nơi chúng ta đang xác thực các trường tên người dùng và mật khẩu. Để đơn giản, chúng được nhúng dưới dạng WebInitParam ngay trong mã servlet. Lưu ý rằng bạn cần sử dụng Servlet 3 để dùng các annotation này, vì vậy bạn cần sử dụng Tomcat-7 hoặc các phiên bản mới hơn có hỗ trợ servlet spec 3.
package com.journaldev.servlet;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebInitParam;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.journaldev.utils.VerifyRecaptcha;
/**
* Servlet implementation class LoginServlet
*/
@WebServlet(description = "Login Servlet", urlPatterns = { "/LoginServlet" }, initParams = {
@WebInitParam(name = "user", value = "Pankaj"),
@WebInitParam(name = "password", value = "journaldev") })
public class LoginServlet extends HttpServlet {
private static final long serialVersionUID = -6506682026701304964L;
protected void doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
// get request parameters for userID and password
String user = request.getParameter("user");
String pwd = request.getParameter("pwd");
// get reCAPTCHA request param
String gRecaptchaResponse = request
.getParameter("g-recaptcha-response");
System.out.println(gRecaptchaResponse);
boolean verify = VerifyRecaptcha.verify(gRecaptchaResponse);
// get servlet config init params
String userID = getServletConfig().getInitParameter("user");
String password = getServletConfig().getInitParameter("password");
// logging example
System.out.println("User=" + user + "::password=" + pwd + "::Captcha Verify"+verify);
if (userID.equals(user) && password.equals(pwd) && verify) {
response.sendRedirect("LoginSuccess.jsp");
} else {
RequestDispatcher rd = getServletContext().getRequestDispatcher(
"/login.html");
PrintWriter out = response.getWriter();
if (verify) {
out.println("<font color=red>Either user name or password is wrong.</font>");
} else {
out.println("<font color=red>You missed the Captcha.</font>");
}
rd.include(request, response);
}
}
}
Khi form có captcha được gửi đi, chúng ta nhận được tham số yêu cầu “g-recaptcha-response” cần thiết để gửi đi xác minh. Phần cuối cùng là lớp tiện ích để gửi yêu cầu POST để xác minh và phân tích cú pháp phản hồi JSON rồi trả về kết quả tương ứng.
package com.journaldev.utils;
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.StringReader;
import java.net.URL;
import javax.json.Json;
import javax.json.JsonObject;
import javax.json.JsonReader;
import javax.net.ssl.HttpsURLConnection;
public class VerifyRecaptcha {
public static final String url = "<https://www.google.com/recaptcha/api/siteverify>";
public static final String secret = "6LdMAgMTAAAAAJOAqKgjWe9DUujd2iyTmzjXilM7";
private final static String USER_AGENT = "Mozilla/5.0";
public static boolean verify(String gRecaptchaResponse) throws IOException {
if (gRecaptchaResponse == null || "".equals(gRecaptchaResponse)) {
return false;
}
try{
URL obj = new URL(url);
HttpsURLConnection con = (HttpsURLConnection) obj.openConnection();
// add reuqest header
con.setRequestMethod("POST");
con.setRequestProperty("User-Agent", USER_AGENT);
con.setRequestProperty("Accept-Language", "en-US,en;q=0.5");
String postParams = "secret=" + secret + "&response="
+ gRecaptchaResponse;
// Send post request
con.setDoOutput(true);
DataOutputStream wr = new DataOutputStream(con.getOutputStream());
wr.writeBytes(postParams);
wr.flush();
wr.close();
int responseCode = con.getResponseCode();
System.out.println("\\nSending 'POST' request to URL : " + url);
System.out.println("Post parameters : " + postParams);
System.out.println("Response Code : " + responseCode);
BufferedReader in = new BufferedReader(new InputStreamReader(
con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
}
in.close();
// print result
System.out.println(response.toString());
//parse JSON response and return 'success' value
JsonReader jsonReader = Json.createReader(new StringReader(response.toString()));
JsonObject jsonObject = jsonReader.readObject();
jsonReader.close();
return jsonObject.getBoolean("success");
}catch(Exception e){
e.printStackTrace();
return false;
}
}
}
Vậy là xong! Ứng dụng của chúng ta đã sẵn sàng. Dưới đây là các trang phản hồi mà chúng ta nhận được dựa trên thông tin đầu vào của người dùng. Trang đăng nhập với tiện ích Google Recaptcha

Google Recaptcha đã được xác thực ở phía client.

Trang phản hồi sau khi xác thực Google Recaptcha ở phía server.

Phản hồi khi Recaptcha chưa được giải quyết.

Recaptcha đã được giải nhưng tên người dùng/mật khẩu không khớp.

Bạn có thể tải xuống dự án từ liên kết dưới đây và thử nghiệm với nó để tìm hiểu thêm. Tải xuống Dự án ứng dụng web Java Google reCAPTCHA