reCAPTCHA v3 - simple example how to use in JavaScript and Spring Framework
In this article we would like to show how to use Google reCAPTCHA v3 with JavaScript and Spring Framework (in Java).
The article consists of 3 parts:
- Google reCAPTCHA v3 panel configuration example,
- front-end code example,
- back-end code example.
Official documentation of reCAPTCHA v3 can be found here.
Simple steps
- configure Google reCAPTCHA:
- go to Google reCAPTCHA panel
https://www.google.com/recaptcha/admin#list - create new configuration,
- type required data (check below screenshot):
- Label (configuration name),
- reCAPTCHA type as v3,
- Domain as
my-domain.com
andlocalhost
for development,
- accept terms and Submit,
- go to Google reCAPTCHA panel
- integrate example codes with yours web site,
- copy source codes from the next sections,
- copy site key into
index.html
file (replace 2 timessite_key_xxyyzz
text - in script url and in variable):<script src="https://www.google.com/recaptcha/api.js?render=site_key_xxyyzz"></script>
var PUBLIC_KEY = 'site_key_xxyyzz';
- copy secret key into
ReCAPTCHAv3Utils.java
file:private static final String SECRET_KEY = "secret_key_xxyyzz";
- open in web browser your web page and check if everything is working correctly.
Notes:
- protect yours secret key!
- set
double SCORES_LEVEL = 0.7
according to yours requirements (read comment in code)- sometimes it is good to do some action if bot behaving is detected (e.g. wait 60 seconds or confirm if you are not bot with yours email).
Google reCAPTCHA v3 panel example
In this section we want to show example configuration for reCAPTCHA v3. Pay attention on localhost
domain if you want to develop yours application with active reCAPTCHA.
Front-end with JavaScript example
In this section login action was used to present reCAPTCHA v3 usage with JavaScript. But we can change login
string to anything different (check: ReCAPTCHAv3Utils.request('login', onSuccess, onError)
).
index.html
file:
// ONLINE-RUNNER:browser;
<!doctype html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.0.0/jquery.min.js"></script>
<!-- reCaptcha v3 key to get on https://www.google.com/recaptcha/admin#list -->
<script src='https://www.google.com/recaptcha/api.js?render=site_key_xxyyzz'></script>
</head>
<body>
<script>
/*
reCaptcha v3 management:
https://www.google.com/recaptcha/admin#list
reCaptcha v3 documentation:
https://developers.google.com/recaptcha/docs/v3
*/
var ReCAPTCHAv3Utils = new function() {
// reCaptcha v3 key to get on https://www.google.com/recaptcha/admin#list
var PUBLIC_KEY = 'site_key_xxyyzz';
// Requests Google reCAPTCHAv3 API to get token.
//
// argument:
// action - we can use own label that describes our action
// Look on "Use case" on the https://developers.google.com/recaptcha/docs/v3
// e.g. homepage, login, social, e-commerce
// onSuccess and onError - callback functions
//
this.request = function(action, onSuccess, onError) {
if (window.grecaptcha) {
window.grecaptcha.ready(function() {
var config = {
action : action
};
try {
var query = window.grecaptcha.execute(PUBLIC_KEY, config);
if (onSuccess) {
query.then(onSuccess);
}
} catch (e) {
var message = e && e.message || 'Captcha request error.';
if (onError) {
onError(message);
}
}
});
} else {
if (onError) {
onError('reCAPTCHA v3 is not loaded correctly.');
}
}
};
};
// Usage example:
function loginUser(data) {
var onSuccess = function(token) {
data.token = token; // <------- token received from Google reCAPTCHA v3
$.ajax({
type: 'POST',
url: '/backend/login-user',
data: JSON.stringify(data),
contentType : 'application/json; charset=utf-8',
dataType : 'json',
success: function(data) {
alert('Response: ' + data.message);
},
error: function(error) {
alert('Request error!');
}
});
};
var onError = function(message) {
alert('Error: ' + message);
};
ReCAPTCHAv3Utils.request('login', onSuccess, onError);
}
loginUser({
username: 'John',
password: 'my-password-here'
});
</script>
</body>
</html>
Back-end with Spring Framework example
In this section, we can find all necessary files that are required to use reCAPTCHA v3 with Spring Framework.
It is necessary to create few files in a project and paste them content - the files are listed below.
pom.xml
file (maven dependences):
<!-- Jackson JSON Mapper -->
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-asl</artifactId>
<version>1.9.10</version>
</dependency>
UserController.java
file:
package logic.controller_captcha;
import logic.util.LoggerUtil;
import org.apache.log4j.Logger;
import javax.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import logic.controller_captcha.recaptchav3.ReCAPTCHAv3Exception;
import logic.controller_captcha.recaptchav3.ReCAPTCHAv3Utils;
import logic.controller_captcha.recaptchav3.ReCAPTCHAv3Response;
@Controller
public class UserController {
private final Logger logger = Logger.getLogger(getClass());
// from 0.0 to 1.0
// 1.0 is very likely a good interaction
// 0.0 is very likely a bot
private final static double SCORES_LEVEL = 0.7;
@RequestMapping(value = "/backend/login-user", method = RequestMethod.POST)
@ResponseBody
public String loginUser(
HttpServletRequest request,
@RequestBody LoginUserRequest loginUserRequest
) {
String token = loginUserRequest.getToken();
String address = request.getRemoteAddr();
try {
ReCAPTCHAv3Response response = ReCAPTCHAv3Utils.request(token, address);
if (response.getSuccess()) {
if (response.getScore() > SCORES_LEVEL) {
// some login operation here ...
return "{\"message\": \"LOGIN SUCCESS\"}";
} else {
return "{\"message\": \"STRANGE BEHAVING DETECTED\"}";
}
}
return "{\"message\": \"ADDRESS OR TOKEN INCORRECT\"}";
} catch (ReCAPTCHAv3Exception e) {
return "{\"message\": \"CAPTCHA ERROR\"}";
}
}
}
LoginUserRequest.java
file:
package logic.controller_captcha;
public class LoginUserRequest
{
private String token;
// other fields here ...
public String getToken() {
return this.token;
}
public void setToken(String token) {
this.token = token;
}
}
ReCAPTCHAv3Utils.java
file:
package logic.controller_captcha.recaptchav3;
import org.codehaus.jackson.map.ObjectMapper;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
/*
reCaptcha v3 management:
https://www.google.com/recaptcha/admin#list
reCaptcha v3 documentation:
https://developers.google.com/recaptcha/docs/v3
*/
public final class ReCAPTCHAv3Utils {
private static ObjectMapper mapper = new ObjectMapper();
// reCaptcha v3 key to get on https://www.google.com/recaptcha/admin#list
private static final String SECRET_KEY = "secret_key_xxyyzz";
private ReCAPTCHAv3Utils() {
// nothing here ...
}
private static String readStream(InputStream stream) throws IOException {
StringBuilder builder = new StringBuilder();
try (BufferedReader reader = new BufferedReader(new InputStreamReader(stream))) {
while (true) {
String line = reader.readLine();
if (line == null) {
break;
}
builder.append(line);
}
}
return builder.toString();
}
private static ReCAPTCHAv3Response readObject(InputStream stream) throws IOException {
String response = readStream(stream);
return mapper.readValue(response, ReCAPTCHAv3Response.class);
}
public static ReCAPTCHAv3Response request(String token, String ip) throws ReCAPTCHAv3Exception {
try {
URL url = new URL("https://www.google.com/recaptcha/api/siteverify?secret="
+ SECRET_KEY + "&response=" + token + "&remoteip=" + ip);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
try {
connection.setRequestMethod("GET");
connection.setConnectTimeout(10000);
connection.setReadTimeout(10000);
return readObject(connection.getInputStream());
} finally {
connection.disconnect();
}
} catch (Exception e) {
throw new ReCAPTCHAv3Exception("Captcha request error.", e);
}
}
}
ReCAPTCHAv3Exception.java
file:
package logic.controller_captcha.recaptchav3;
public class ReCAPTCHAv3Exception extends Throwable {
public ReCAPTCHAv3Exception(String message) {
super( message );
}
public ReCAPTCHAv3Exception(String message, Throwable cause) {
super( message, cause );
}
}
ReCAPTCHAv3Response.java
file:
package logic.controller_captcha.recaptchav3;
import org.codehaus.jackson.annotate.JsonProperty;
public class ReCAPTCHAv3Response {
@JsonProperty( "success" )
private boolean success;
@JsonProperty( "score" )
private double score;
@JsonProperty( "action" )
private String action;
@JsonProperty( "challenge_ts" )
private Object timestamp;
@JsonProperty( "hostname" )
private String hostname;
@JsonProperty( "error-codes" )
private Object errors;
public boolean getSuccess() {
return this.success;
}
public void setSuccess(boolean success) {
this.success = success;
}
public double getScore() {
return this.score;
}
public void setScore(double score) {
this.score = score;
}
public String getAction() {
return this.action;
}
public void setAction(String action) {
this.action = action;
}
public String getHostname() {
return this.hostname;
}
public void setHostname(String hostname) {
this.hostname = hostname;
}
}