reCAPTCHA Enterprise mit Ruby lösen

Von solvethree4 Min. Lesezeit

Verwenden Sie Rubys Net::HTTP, um eine reCAPTCHA Enterprise-Aufgabe zu erstellen und ihren Status abzufragen, bis sie fertig oder fehlgeschlagen ist. Das folgende Beispiel ruft die REST-API von solvethree direkt auf; ein Ruby SDK ist dafür nicht erforderlich.

Auf dieser Seite

Website und Umgebung konfigurieren

  1. 1.

    Websiteprofil aktivieren

    Richten Sie den Zielhostname in der solvethree-Konsole ein und stellen Sie sicher, dass sein Profil für Ihren Arbeitsbereich aktiv ist. Das Senden eines Hostnamens und einer Aktion erstellt kein Profil. Siehe Website-Profil einrichten.

  2. 2.

    Umgebungsvariablen festlegen

    Setzen Sie SOLVETHREE_API_KEY auf den API-Schlüssel Ihres Arbeitsbereichs und SOLVETHREE_PROXY auf die HTTP- oder HTTPS-Proxy-URL, die Sie auch beim Übermitteln des Tokens an das Ziel verwenden werden. Bewahren Sie den Schlüssel auf dem Server auf.

  3. 3.

    Beispieleingaben ändern

    Ersetzen Sie accounts.example.com durch den Zielhostname – keine vollständige URL – und login durch die vom Ziel erforderte Aktion. Die Anfrage verwendet einen einzelnen proxy; fügen Sie nicht zusätzlich proxyCandidates hinzu. Lassen Sie type und url weg. Wenn Sie recaptchaType weglassen, wird der Standardwert enterprise-v3 gewählt.

Speichern Sie das Beispiel als solve.rb und führen Sie es mit Ruby aus, nachdem Sie diese Variablen gesetzt haben. Es lädt net/http, json und securerandom; JSON verarbeitet den Anfrageinhalt und die API-Antworten.

Einmal erstellen, dann die Aufgaben-ID abfragen

Ruby · Einmaliges Erstellen und endliches Polling
require 'net/http'
require 'json'
require 'securerandom'

api = 'https://api.solvethree.com/v1'
input = {site: 'accounts.example.com', action: 'login', proxy: ENV.fetch('SOLVETHREE_PROXY'), requestId: SecureRandom.uuid}
deadline = Process.clock_gettime(Process::CLOCK_MONOTONIC) + 180
call = lambda do |method, path, body = nil|
  remaining = deadline - Process.clock_gettime(Process::CLOCK_MONOTONIC)
  raise 'Local deadline reached' if remaining <= 0
  uri = URI(api + path)
  request = method == :post ? Net::HTTP::Post.new(uri) : Net::HTTP::Get.new(uri)
  request['Authorization'] = 'Bearer ' + ENV.fetch('SOLVETHREE_API_KEY')
  request['Accept'] = 'application/json'
  if body
    request['Content-Type'] = 'application/json'
    request.body = JSON.generate(body)
  end
  # Net::HTTP's own proxy configuration is separate from input[:proxy].
  http = Net::HTTP.new(uri.hostname, uri.port, nil)
  http.use_ssl = uri.scheme == 'https'
  http.open_timeout = [10, remaining].min
  http.read_timeout = [25, remaining].min
  http.write_timeout = [25, remaining].min
  http.max_retries = 0
  response = http.request(request)
  raise "API HTTP #{response.code}" unless response.is_a?(Net::HTTPSuccess)
  JSON.parse(response.body)
end

task_id = nil
begin
  result = call.call(:post, '/tasks?waitMs=0', input)
  task_id = result.fetch('id')
  while %w[pending solving].include?(result.fetch('status'))
    result = call.call(:get, '/tasks/' + URI.encode_www_form_component(task_id) + '?waitMs=15000')
    sleep(1) if %w[pending solving].include?(result.fetch('status'))
  end
  raise "Task failed: #{result['errorCode']}" unless result['status'] == 'ready'
  puts "Ready task: #{task_id}"
  # Submit result['solution']['token'] with its userAgent/secChUa and original proxy.
rescue StandardError => error
  warn "Recovery requestId=#{input[:requestId]} taskId=#{task_id || 'unknown'}"
  raise error
end

Das Skript sendet eine einzelne Erstellungsanfrage, speichert die zurückgegebene Aufgaben-ID und ruft diese Aufgabe ab, solange ihr Status pending oder solving ist. Nur ready liefert eine nutzbare Lösung. Jede Antwort muss einen erfolgreichen HTTP-Status haben, bevor ihr Inhalt als Erfolgsantwort geparst wird.

HTTPS ist explizit aktiviert. Automatische Wiederholungen sind deaktiviert, und Weiterleitungen werden durch die HTTP-Statusprüfung abgewiesen, statt ihnen zu folgen. Der Proxy im Aufgabeninhalt dient dem Lösungsvorgang; er konfiguriert nicht die Verbindung von Ruby zur solvethree-API.

Die gemeinsame monotone Frist gibt den Statusabfragen ein lokales Zeitbudget von 180 Sekunden. Verbindungs-, Lese- und Schreibzeitlimits werden anhand der beim Start jeder Anfrage verbleibenden Zeit begrenzt. Betrachten Sie dieses Budget als Grenze für Statusabfragen, nicht als festen Abbruchzeitpunkt für eine laufende Anfrage. Die Dokumentation zu Ruby Net::HTTP beschreibt die einzelnen Zeitlimiteinstellungen.

Token mit seiner Browseridentität übermitteln

Das Beispiel gibt die ID der fertigen Aufgabe aus, nicht das Token. Lesen Sie solution.token aus dem fertigen Ergebnis und setzen Sie es in das von der Zielanfrage erwartete Token-Feld ein. Senden Sie stattdessen nicht die Aufgaben-ID.

Verwenden Sie den zurückgegebenen Wert solution.userAgent für den Header User-Agent und solution.secChUa für Sec-CH-UA. Übermitteln Sie die Anfrage über denselben Proxy, der dieser Aufgabe übergeben wurde, an das vorgesehene Ziel. Ersetzen Sie die zurückgegebene Identität nicht durch Header eines anderen Browsers.

Eine fertige Aufgabe bedeutet, dass solvethree eine Lösung generiert hat. Prüfen Sie die Antwort des Ziels separat, um festzustellen, ob es Ihre Anwendungsanfrage akzeptiert hat.

Fehler behandeln, ohne doppelte Aufgaben zu erstellen

Das Skript löst einen API-HTTP-Fehler aus.

Untersuchen Sie die nicht erfolgreiche HTTP-Antwort. Dies ist ein Fehler auf Anfrageebene, kein endgültiges Aufgabenergebnis.

Probiere Folgendes: Analysieren Sie diese Antwort vor einem erneuten Versuch. Senden Sie unveränderte ungültige Eingaben nicht wiederholt.

Die Aufgabe erreicht den Status failed.

Prüfen Sie sowohl errorCode als auch error im Ergebnis. Die vom Beispiel ausgelöste Fehlermeldung enthält nur errorCode.

Probiere Folgendes: Beenden Sie die Statusabfragen für diese Aufgabe und beheben Sie die gemeldete Ursache. Fehlgeschlagene Lösungsvorgänge werden erstattet; ein Fehlschlag bedeutet nicht zwangsläufig, dass das Guthaben nicht ausreicht.

Beim Erstellen tritt eine Zeitüberschreitung auf, bevor eine Aufgaben-ID empfangen wird.

Bewahren Sie die zur Wiederherstellung auf der Standardfehlerausgabe ausgegebene requestId auf. Eine Zeitüberschreitung beweist nicht, dass die Erstellung fehlgeschlagen ist.

Probiere Folgendes: Stellen Sie den Vorgang wieder her, indem Sie die identische Aufgabenanfrage mit derselben Anfrage-ID senden. Führen Sie das Skript nicht einfach erneut aus: Ein neuer Durchlauf generiert eine neue ID und erstellt möglicherweise eine weitere Aufgabe.

Die Statusabfrage erreicht die lokale Frist oder verliert die Verbindung.

Bewahren Sie die protokollierte Aufgaben-ID und Anfrage-ID auf.

Probiere Folgendes: Rufen Sie die bekannte Aufgaben-ID ab, bevor Sie eine weitere Aufgabe erstellen. Eine lokale Ausnahme ist kein endgültiger Aufgabenstatus.

Für eine Wiederherstellung nach Prozessneustarts speichern Sie die Anfrage-ID und die ursprünglichen Aufgabeneingaben vor dem Senden des POST und anschließend die Aufgaben-ID, sobald sie zurückgegeben wird. Die Wiederverwendung einer Anfrage-ID mit identischen Eingaben gibt die vorhandene Aufgabe zurück; geänderte Eingaben bei gleichbleibender ID verursachen einen Konflikt. Den nächsten Diagnoseschritt finden Sie unter API-Fehlerbehandlung.

Führe deinen ersten Task aus.

Starte mit $5 Workspace-Guthaben.

Workspace erstellen
reCAPTCHA Enterprise mit Ruby lösen · solvethree