This Java client integrates with Google's reCAPTCHA v2 and supports Cloudflare's Turnstile. It includes a Spring Boot starter for easy integration into your applications.
Warning
The API is in beta, expect breaking changes.
<properties>
<recaptcha.version>0.4.0</recaptcha.version>
</properties>
<dependencies>
<dependency>
<groupId>dev.caceresenzo.recaptcha</groupId>
<artifactId>recaptcha-v2-validator</artifactId>
<version>${recaptcha.version}</version>
</dependency>
</dependencies>ReCaptchaV2Validatorvalidator = ReCaptchaV2Validator.builder()
.secretKey("6LeIxAcTAAAAAJcZVRqyHh71UMIEGNQ_MXjiZKhI")
.build();
/* or with the test secret key */ReCaptchaV2Validatorvalidator = ReCaptchaV2Validator.builder()
.testSecretKey()
.build();ReCaptchaV2Validatorvalidator = ReCaptchaV2Validator.turnstile()
.secretKey("1x00000000000000000000AA")
.build();
/* or with the test secret key */ReCaptchaV2Validatorvalidator = ReCaptchaV2Validator.builder()
.alwaysPassesTestSecretKey()
.build();ReCaptchaV2Responseresponse = validator.verify("abcdefijklmnopqrstuvwxyz");
/* throws an exception if there is an error */response.orThrow();
/* use pattern matching to decide */switch (response) {
caseReCaptchaV2Response.Successsuccess -> {
System.out.println("Challenge passed!");
}
caseReCaptchaV2Response.Failurefailure -> {
System.err.println("Challenge failed: %s".formatted(failure.message()));
}
}Note
The usage is the same for Cloudflare Turnstile.
There is a Spring Boot auto-configuration available.
<dependencies>
<dependency>
<groupId>dev.caceresenzo.recaptcha</groupId>
<artifactId>recaptcha-v2-spring-boot-starter</artifactId>
<version>${recaptcha.version}</version>
</dependency>
</dependencies>Which is enabled when the Secret Key is specified in the configuration:
recaptcha:
v2:
secret-key: 6LeIxAcTAAAAAJcZVRqyHh71UMIEGNQ_MXjiZKhI# Configure the web integrationweb:
# Change the default response location (either HEADER or QUERY)location: QUERY# Change the default header name (if the location is HEADER)header-name: X-ReCaptcha-Response# Change the default query parameter name (if the location is QUERY)query-parameter-name: reCaptchaResponseNote
The default service used is Google reCAPTCHA V2.
You can use Cloudflare Turnstile simply by setting the service property and using the correct secret key. Other configurations and usage remain the same.
recaptcha:
v2:
# Use Cloudflare Turnstile serviceservice: CLOUDFLARE_TURNSTILEsecret-key: 1x0000000000000000000000000000000AAIf the response is not manually handled, a custom behavior can be specified to handle the result.
@Configuration(proxyBeanMethods = false)
@RequiredArgsConstructorpublicclassReCaptchaConfiguration {
@BeanReCaptchaV2AnnotationInterceptor.ResponseHandlerreCaptchaV2AnnotationInterceptorResponseHandler() {
return (response) -> response.orThrowWithMessage(MyCustomException::new);
}
}To protect an endpoint, simply annotate it with the @ReCaptchaV2 annotation.
@RestController@RequestMapping(path = "/hello", produces = MediaType.APPLICATION_JSON_VALUE)
publicclassHelloRestController {
@ReCaptchaV2@GetMappingpublicStringnoSpam() {
return"Challenge passed!";
}
}Instead of having the error thrown automatically, you can manually handle the result by requesting the ReCaptchaV2Response parameter.
The behavior is similar to Spring's `BindingResult'.
@ReCaptchaV2@GetMappingpublicStringnoSpam(
ReCaptchaV2ResponsereCaptchaResponse
) {
if (isSpamProtectionEnabledGlobally()) {
reCaptchaResponse.orThrow();
}
return"Challenge passed!";
}The behavior will change based on the response type specified in the parameter.
| Parameter Type | Auto. Throw | How to handle |
|---|---|---|
(none) | Yes | Success is expected by default. Bind errors will be thrown, and the response handler will be used. |
ReCaptchaV2Response | No | Response must be handled by the user. Bind errors are muted and treated like regular failures. |
ReCaptchaV2Response.Success | Yes | Success is expected. Same behavior as for (none). |
ReCaptchaV2Response.Failure | Partial | Failure is expected. Bind errors will be thrown, but the response must be handled by the user. |
Note
Bind errors are MissingRequestHeaderException and MissingServletRequestParameterException.
If they are muted, they will be replaced with missing-input-response.
Warning
A response might be null if it does not correspond.
For example, the ReCaptchaV2Response is .Success, but the required type is .Failure (and vice versa).
If there are some legacy endpoints, they can also be customized to locate the challenge response from a different location than the globally defined one.
@ReCaptchaV2(
location = ChallengeResponseLocation.QUERY,
name = "captcha"
)
@GetMappingpublicStringnoSpam() {
return"Challenge passed!";
}When SpringDoc OpenAPI is detected and an endpoint is annotated with the @ReCaptchaV2 annotation, the Swagger Operation will automatically have the necessary query/header parameter to the spec.