Skip to content

Repository files navigation

reCAPTCHA v2 for Java

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.

Installation

<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>

Configuration

ReCaptchaV2Validatorvalidator = ReCaptchaV2Validator.builder()
.secretKey("6LeIxAcTAAAAAJcZVRqyHh71UMIEGNQ_MXjiZKhI")
.build();
/* or with the test secret key */ReCaptchaV2Validatorvalidator = ReCaptchaV2Validator.builder()
.testSecretKey()
.build();

Cloudflare Turnstile

ReCaptchaV2Validatorvalidator = ReCaptchaV2Validator.turnstile()
.secretKey("1x00000000000000000000AA")
.build();
/* or with the test secret key */ReCaptchaV2Validatorvalidator = ReCaptchaV2Validator.builder()
.alwaysPassesTestSecretKey()
.build();

Usage

Verify a Challenge Response

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.

Spring Boot Starter

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: reCaptchaResponse

Note

The default service used is Google reCAPTCHA V2.

Cloudflare Turnstile

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: 1x0000000000000000000000000000000AA

Custom Handling

If 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);
}
}

Controller Examples

General Case

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!";
}
}

Manually handling the result

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!";
}

Typed handling of the result

The behavior will change based on the response type specified in the parameter.

Parameter TypeAuto. ThrowHow to handle
(none)YesSuccess is expected by default.
Bind errors will be thrown, and the response handler will be used.
ReCaptchaV2ResponseNoResponse must be handled by the user.
Bind errors are muted and treated like regular failures.
ReCaptchaV2Response.SuccessYesSuccess is expected.
Same behavior as for (none).
ReCaptchaV2Response.FailurePartialFailure 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).

Endpoint-specific configuration

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!";
}

Spring Doc Integration

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.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages