Architektur
CaptchaService ist eine einzelne Spring-Boot-Anwendung mit einer PostgreSQL-Datenbank im Hintergrund. Sämtlicher öffentlicher Traffic kommt über CaptchaController herein und wird an eine schmale Service-Schicht delegiert; JPA-Repositories speichern den Zustand von Challenges und Entwertungen in PostgreSQL.
Komponentendiagramm
graph TB
%% Externer Client
Client
%% Externe Dienste
subgraph "Externe Dienste"
PostgreSQL[(PostgreSQL<br/>Datenbank)]
end
%% CaptchaService-Anwendung
subgraph "CaptchaService Application"
%% Monitoring & Management
subgraph "Monitoring"
Actuator["**Spring Actuator**<br/>/actuator/info<br/>/actuator/health<br/>/actuator/metrics"]
end
%% API-Endpunkte
subgraph "CaptchaController"
ChallengeEndpoint["**postChallenge()**<br/>CAPTCHA-Challenge erzeugen"]
VerifyEndpoint["**postVerify()**<br/>CAPTCHA-Lösung prüfen"]
end
%% Service-Schicht
subgraph "Service-Schicht"
CaptchaService["**CaptchaService**<br/>Kernlogik"]
DifficultyService["**DifficultyService**<br/>adaptive Schwierigkeit"]
SiteAuthService["**SiteAuthService**<br/>Site-Key/-Secret prüfen"]
SourceAddressService["**SourceAddressService**<br/>IP-Validierung"]
ExpiredDataService["**ExpiredDataService**<br/>geplante Bereinigung"]
end
%% Daten-Schicht
subgraph "Daten-Schicht"
CaptchaRequestRepo["**CaptchaRequestRepository**<br/>JPA-Repository"]
InvalidatedPayloadRepo["**InvalidatedPayloadRepository**<br/>JPA-Repository"]
subgraph "JPA-Entitäten"
CaptchaRequestEntity["**CaptchaRequest**<br/>Entität"]
InvalidatedPayloadEntity["**InvalidatedPayload**<br/>Entität"]
end
end
%% Konfiguration
subgraph "Konfigurations-Properties"
CaptchaProperties["**CaptchaProperties**<br/>HMAC-Key, Sites"]
CaptchaSite["**CaptchaSite**<br/>Site-spezifische Einstellungen"]
DifficultyItem["**DifficultyItem**<br/>Schwierigkeits-Mappings"]
end
end
%% Anfragefluss
Client -->|POST /api/v1/challenge| ChallengeEndpoint
Client -->|POST /api/v1/verify| VerifyEndpoint
Client --> Monitoring
%% Controller -> Services
ChallengeEndpoint --> CaptchaService
VerifyEndpoint --> CaptchaService
ChallengeEndpoint --> SiteAuthService
VerifyEndpoint --> SiteAuthService
ChallengeEndpoint --> SourceAddressService
%% Service-Interaktionen
CaptchaService --> DifficultyService
CaptchaService --> CaptchaRequestRepo
CaptchaService --> InvalidatedPayloadRepo
CaptchaService --> AltchaLib
DifficultyService --> CaptchaRequestRepo
ExpiredDataService -->|geplante Bereinigung| CaptchaRequestRepo
ExpiredDataService -->|geplante Bereinigung| InvalidatedPayloadRepo
%% Daten-Schicht
CaptchaRequestRepo --> CaptchaRequestEntity
InvalidatedPayloadRepo --> InvalidatedPayloadEntity
CaptchaRequestEntity -.->|JPA/Hibernate| PostgreSQL
InvalidatedPayloadEntity -.->|JPA/Hibernate| PostgreSQL
%% Konfigurations-Abhängigkeiten
CaptchaService -.->|nutzt| CaptchaProperties
SiteAuthService -.->|nutzt| CaptchaProperties
SourceAddressService -.->|nutzt| CaptchaProperties
DifficultyService -.->|nutzt| CaptchaProperties
%% Datenbankmigration
Flyway -.->|Schema-Verwaltung| PostgreSQL
Komponenten
CaptchaController— REST-Einstiegspunkt. StelltPOST /api/v1/captcha/challengeundPOST /api/v1/captcha/verifybereit.CaptchaService— erzeugt und verifiziert Challenges; kapselt die ALTCHA-Bibliothek.DifficultyService— bestimmt die Schwierigkeit pro Site und Quell-IP anhand des jüngsten Anfrageverhaltens.SiteAuthService— prüft das von Clients mitgeschicktesiteKey/siteSecret-Paar.SourceAddressService— validiert die Client-IP gegen die Site-Allowlist bzw. das Beobachtungsfenster.ExpiredDataService— geplanter Job, der abgelaufene Challenges und entwertete Payloads löscht.- JPA-Schicht — zwei Repositories (
CaptchaRequestRepository,InvalidatedPayloadRepository), Hibernate-Entitäten, PostgreSQL. - Flyway — verwaltet Schema-Migrationen unter
src/main/resources/db/migration/. - Spring Actuator — stellt
/actuator/health,/actuator/info,/actuator/metricsund/actuator/prometheusbereit.
Anfragefluss
- Der Client schickt
siteKey,siteSecretundclientAddressper POST an/api/v1/captcha/challenge. SiteAuthServiceauthentifiziert die Site,SourceAddressServiceprüft die IP,DifficultyServicewählt die passende Schwierigkeit anhand der Site-Schwierigkeits-Map und der jüngsten Aufrufe.CaptchaServicelässt ALTCHA eine signierte Challenge erzeugen, persistiert einenCaptchaRequestund liefert die Challenge zurück.- Der Client löst den Proof-of-Work und schickt den gelösten Payload per POST an
/api/v1/captcha/verify. CaptchaServiceprüft Signatur und HMAC, markiert den Payload als entwertet (damit er nicht erneut verwendet werden kann) und antwortet mit{ "valid": true | false }.