Java¶
Für Java stehen drei Clients bereit. Alle drei sind aus derselben OpenAPI-Beschreibung erzeugt und rufen denselben Endpunkt auf. Sie unterscheiden sich in der verwendeten Technik von Spring.
Client wählen¶
| Anwendung | Client |
|---|---|
| Spring Boot 3 mit Jakarta EE | java-webflux-boot3 |
| Spring Boot 2 oder Spring 5, reaktiv | java-webflux-boot2 |
| Spring MVC auf dem Servlet-Stapel, Spring 6 | java-resttemplate |
| Client | Voraussetzungen | Schnittstelle |
|---|---|---|
java-resttemplate |
Java 17, Spring Framework 6 | Synchron: VerifyResponse verifyClientToken(VerifyRequest). Wiederholt Anfragen bei den Statuscodes 5xx und 429 mit wachsendem Abstand. |
java-webflux-boot2 |
Java 8, Spring Boot 2 mit Spring WebFlux | Reaktiv: Mono<VerifyResponse> verifyClientToken(VerifyRequest) |
java-webflux-boot3 |
Java 17, Spring Boot 3 mit Jakarta EE 10 | Reaktiv: Mono<VerifyResponse> verifyClientToken(VerifyRequest). Verwendet durchgehend Anmerkungen aus jakarta.*. |
Client einbinden¶
Binden Sie den gewählten Client mit Maven ein, hier am Beispiel von java-resttemplate:
<dependency>
<groupId>com.myrasec</groupId>
<artifactId>eu-captcha-java-resttemplate</artifactId>
<version>1.0.0</version>
<scope>compile</scope>
</dependency>
Mit Gradle lautet der Eintrag:
Aus den Quellen erzeugen Sie den Client mit:
Token prüfen¶
Das folgende Beispiel zeigt die synchrone Prüfung mit java-resttemplate:
import com.myrasec.client.ApiClient;
import com.myrasec.client.api.EuCaptchaApi;
import com.myrasec.client.model.VerifyRequest;
import com.myrasec.client.model.VerifyResponse;
import org.springframework.web.client.RestClientException;
ApiClient client = new ApiClient();
// client.setMaxAttemptsForRetry(3); // optional: retry up to 3 times on 5xx / 429
EuCaptchaApi api = new EuCaptchaApi(client);
VerifyRequest request = new VerifyRequest()
.sitekey("YOUR_SITEKEY")
.secret("YOUR_SECRET")
.clientIp(clientIp) // real end-user IP — see below
.clientToken(euCaptchaToken) // value of the "eu-captcha-response" POST field
.clientUserAgent(userAgent); // value of the User-Agent request header
try {
VerifyResponse response = api.verifyClientToken(request);
if (response.isTrainingMode()) {
// Training mode: real validation was not performed — always allow.
// Occurs when the sitekey does not exist, the secret is wrong,
// or the sitekey is configured with train=true.
allowAccess();
} else if (Boolean.TRUE.equals(response.getSuccess())) {
allowAccess();
} else {
denyAccess();
}
} catch (RestClientException e) {
// Network error or unexpected HTTP status.
// Decide your fallback policy: allow or deny.
log.error("EU CAPTCHA verification failed: {}", e.getMessage());
}
Reaktive Prüfung¶
Die beiden Clients für WebFlux geben ein Mono<VerifyResponse> zurück. Fügen Sie dieses in Ihre Verarbeitungskette ein, statt .block() aufzurufen:
import com.myrasec.client.ApiClient;
import com.myrasec.client.api.EuCaptchaApi;
import com.myrasec.client.model.VerifyRequest;
import com.myrasec.client.model.VerifyResponse;
import org.springframework.web.reactive.function.client.WebClientResponseException;
import reactor.core.publisher.Mono;
ApiClient client = new ApiClient(); // thread-safe; share a single instance
EuCaptchaApi api = new EuCaptchaApi(client);
VerifyRequest request = new VerifyRequest()
.sitekey("YOUR_SITEKEY")
.secret("YOUR_SECRET")
.clientIp(clientIp)
.clientToken(euCaptchaToken)
.clientUserAgent(userAgent);
Mono<VerifyResponse> result = api.verifyClientToken(request)
.map(response -> {
if (response.isTrainingMode()) {
allowAccess();
} else if (Boolean.TRUE.equals(response.getSuccess())) {
allowAccess();
} else {
denyAccess();
}
return response;
})
.onErrorResume(WebClientResponseException.class, e -> {
log.error("EU CAPTCHA verification failed: {}", e.getMessage());
return Mono.empty();
});
IP-Adresse des Besuchers ermitteln¶
Übergeben Sie stets die tatsächliche IP-Adresse des Besuchers, nicht die Adresse Ihres vorgelagerten Systems.
In einer Anwendung auf dem Servlet-Stapel:
// Without a proxy
String clientIp = httpServletRequest.getRemoteAddr();
// Behind a reverse proxy or CDN (use the header your provider documents)
String forwarded = httpServletRequest.getHeader("X-Forwarded-For");
if (forwarded != null && !forwarded.isBlank()) {
// X-Forwarded-For is a comma-separated list; the leftmost entry is the client IP
clientIp = forwarded.split(",")[0].trim();
}
In einer Anwendung mit WebFlux:
// In a Spring WebFlux handler (ServerWebExchange)
String clientIp = exchange.getRequest().getRemoteAddress().getAddress().getHostAddress();
// Behind a reverse proxy or CDN (use the header your provider documents)
String forwarded = exchange.getRequest().getHeaders().getFirst("X-Forwarded-For");
if (forwarded != null && !forwarded.isBlank()) {
clientIp = forwarded.split(",")[0].trim();
}
Die Kopfzeile X-Forwarded-For enthält eine durch Kommata getrennte Liste. Der erste Eintrag ist die IP-Adresse des Besuchers.
Felder der Anfrage¶
| Feld | Typ | Pflicht | Inhalt |
|---|---|---|---|
sitekey |
String | ja | Öffentlicher Sitekey aus der Ansicht Details. |
secret |
String | ja | Geheimer Schlüssel zum Sitekey. |
clientIp |
String | ja | IPv4- oder IPv6-Adresse des Besuchers. |
clientToken |
String | ja | Token aus verify.js. Der Wert darf leer sein. |
clientUserAgent |
String | ja | Wert der Kopfzeile User-Agent aus der Anfrage des Besuchers. |
Felder der Antwort¶
| Feld | Typ | Inhalt |
|---|---|---|
success |
Boolean | true, wenn die Challenge bestanden wurde. |
train |
Boolean | true, wenn der Trainingsbetrieb aktiv war. Die Methode isTrainingMode() liest dieses Feld. |
Der Endpunkt liegt unter https://api.eu-captcha.eu/v1 und lautet POST /verify. Eine Anmeldung ist nicht erforderlich. Die Anfrage weist sich über das Feld secret aus.
Sicherheit¶
Warning
Schalten Sie ApiClient.setDebugging(true) nicht im Produktivbetrieb ein. Im Fehlersuchbetrieb schreibt der Client den vollständigen JSON-Rumpf in das Protokoll. VerifyRequest.toString() verbirgt das Secret, der tatsächlich übertragene Rumpf jedoch nicht.
Legen Sie das Secret in einer Umgebungsvariablen oder in einer Schlüsselverwaltung ab, niemals im Quelltext.
ApiClient ist nebenläufigkeitssicher. Erzeugen Sie eine Instanz und verwenden Sie sie in der gesamten Anwendung, statt je Anfrage eine neue Instanz anzulegen.
Vollständiges Beispiel¶
Siehe Angular und Java.