I never liked Captchas because the burden was always on end user to understand the letters and prove that he is a human and not a software bot. But when I recently saw new Google reCAPTCHA on a website, I instantly liked it. Because all we need is to check a box and it will figure out if you are a human or robot. Google is calling it No CAPTCHA reCAPTCHA experience and it uses an advanced risk analysis engine and adaptive CAPTCHAs to keep automated software from engaging in abusive activities on your site. So that formed the basis of this post where I will show you how to utilize Google reCAPTCHA in your java based web application. Before we move on with our project, first thing you need to do is go to Google reCAPTCHA and sign up. After that you will get a Site key that is used to display the reCaptcha widget on your web pages. You will also get a Secret key that should be kept secret and used in communicating with Google server to verify the captcha response. After I registered a test site, I got below keys and I will utilize them in my project. Note that while signup you also need to provide domain name and the keys will work only on that domain name. Also keys will always work on localhost, so I can easily test it on my local server. Now we can head over to our example project. We will have a login page where user will enter username and password, apart from that he will also have to solve reCaptcha and submit the form. Once the form is submitted, username and password will be validated in our application, whereas we will send the captcha response with secret key to Google reCaptcha server and get the response. The response from Google reCaptcha is a JSON with a success boolean field, if validated success value will be true otherwise it will be false. I will use Java JSON Processing API to parse the response JSON. Below image shows our final project in Eclipse. To get the project skeleton, just create a “Dynamic Web Project” in Eclipse and then convert it to Maven project. Just add below dependency in pom.xml
file for JSON API.
<dependency>
<groupId>org.glassfish</groupId>
<artifactId>javax.json</artifactId>
<version>1.0.2</version>
</dependency>
Let’s look into each of the components one by one.
Below is our login html page code. 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>
We need to add Google reCaptcha JS file in the HTML head section and then add <div class="g-recaptcha" data-sitekey="Site-key"></div>
in our form to get the reCaptcha widget. That’s all at the client side, it’s really this simple! Once user is validated he will be sent to below success page. 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>
Below is our simple LoginServlet.java servlet code where we are validating username and password fields. For simplicity, they are embedded as WebInitParam
in the servlet code itself. Note that you need to use Servlet 3 to use these annotations, so you need to use Tomcat-7 or later versions that support 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);
}
}
}
Once form with captcha is submitted, we get “g-recaptcha-response” request parameter that is required to send for verification. The last part is the utility class to send POST request for verification and parse the JSON response and return accordingly.
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;
}
}
}
That’s all. Our application is ready, below are the response pages we get based on user inputs. Login Page with Google Recaptcha Widget Google Recaptcha Validated at client side Response page after server side Google Recaptcha Validation Response where Recaptcha was not solved Recaptcha Solved but user/password didn’t match You can download the project from below link and play around with it to learn more.
Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.
While we believe that this content benefits our community, we have not yet thoroughly reviewed it. If you have any suggestions for improvements, please let us know by clicking the “report an issue“ button at the bottom of the tutorial.
I’m getting below error on JSF page: Uncaught (in promise) SyntaxError: Unexpected token � in JSON at position 0 at JSON.parse () at recaptcha__en.js:59 at recaptcha__en.js:81 at Array. (recaptcha__en.js:93) at Array. (recaptcha__en.js:80) at KA.B (recaptcha__en.js:59) at Array. (recaptcha__en.js:53) at Hf.next (recaptcha__en.js:259) at h (recaptcha__en.js:325) Can you please help with this?
- Manisha
Very good! I made a version with JSF / ManagedBean / Controller based in you example and works! Thanks!
- André Hiroshi Tanaka
Thank you for sharing!
- Vu Nguyen
Getting NULL value of reCaptcha response.
- Hema
“Localhost is not in the list of supported domains for this site key” i keep seeing this in the captcha, i have given the label and the domain name as localhost.Please help me resolve this.
- jojo
i ran the codein the eclipse and i gave the corresponding keys the site key and the security key,but it shows that error with the captcha site owner.Please help
- shajo
Hi Pankaj, I am receiving below exception while implementing google captcha on localhost javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target. Please help
- Prakash
Hi Pankaj, I ma receiving below exception at localhost. 19/04/15 07:18:58 java.net.ConnectException: Connection refused: connect 19/04/15 07:18:58 at java.net.PlainSocketImpl.socketConnect(Native Method)
- Prakash
Hello Pankaj sir, i got an error : Localhost is not in the list of supported domains for this site key. please help me.
- Tejas Dahake
This code is not working on IE11
- Ali Bahadar