קריאה ל-API של CAPTCHA מתוך Spring Boot

מאת solvethree4 דקות קריאה

רשמו bean אחד מסוג CaptchaClient בצד השרת, צרו משימה פעם אחת ואז בצעו תשאול באמצעות המזהה ששמרתם. מחלקת העזר שלהלן משתמשת בקריאות סינכרוניות של Spring RestClient ומחזירה תגובות מסוג Gson JsonObject.

בדף הזה

הוספת התלויות ורישום מחלקת העזר

מחלקת העזר המצורפת משתמשת ב-Java 21+, ב-Spring Web 7.0.10 וב-Gson 2.15.0. בפרויקט Spring Boot קיים, השאירו את גרסת Spring התואמת שמנוהלת על ידי Boot במקום לעקוף רק את הגרסה של spring-web כדי להתאים לדוגמה. הוסיפו את Gson כתלות אם הוא עדיין לא נכלל באפליקציה שלכם.

Spring · שירות RestClient בצד השרת
// Java 21+, Spring Web 7.0.10 and Gson 2.15.0; use your Boot dependency management.
// Save as CaptchaClient.java in your application's package.
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import java.net.http.HttpClient;
import java.time.Duration;
import org.springframework.http.MediaType;
import org.springframework.http.client.JdkClientHttpRequestFactory;
import org.springframework.web.client.RestClient;

public final class CaptchaClient {
    private final RestClient api;
    public CaptchaClient(String key) {
        var transport = HttpClient.newBuilder().connectTimeout(Duration.ofSeconds(10))
            .followRedirects(HttpClient.Redirect.NEVER).build();
        var factory = new JdkClientHttpRequestFactory(transport);
        factory.setReadTimeout(Duration.ofSeconds(25));
        api = RestClient.builder().baseUrl("https://api.solvethree.com/v1")
            .requestFactory(factory).defaultHeader("Authorization", "Bearer " + key).build();
    }
    public JsonObject create(String site, String proxy, String requestId) {
        var input = new JsonObject();
        input.addProperty("site", site);
        input.addProperty("action", "login");
        input.addProperty("proxy", proxy);
        input.addProperty("requestId", requestId); // Save before calling create.
        String body = api.post().uri("/tasks?waitMs=0").contentType(MediaType.APPLICATION_JSON)
            .body(input.toString()).retrieve().body(String.class);
        return JsonParser.parseString(body).getAsJsonObject();
    }
    public JsonObject get(String id) {
        if (!id.matches("[A-Za-z0-9_-]+")) throw new IllegalArgumentException("Invalid task ID");
        String body = api.get().uri("/tasks/{id}?waitMs=15000", id)
            .retrieve().body(String.class);
        return JsonParser.parseString(body).getAsJsonObject();
    }
}
// Construct once with System.getenv("SOLVETHREE_API_KEY") in a server-side @Bean.
// Call create once, save its id, then get(id) until ready/failed or your deadline.
// RestClient throws on HTTP errors; keep the saved requestId and any known task id.

שמרו את המחלקה בשם CaptchaClient.java בחבילה של האפליקציה. במתודת מפעל מסוג @Bean בצד השרת, צרו מופע שלה פעם אחת באמצעות משתנה הסביבה SOLVETHREE_API_KEY. בדקו בעת האתחול שהמפתח מוגדר. מחלקת העזר מוסיפה אותו ככותרת הרשאה מסוג Bearer; אל תכללו אותו בקוד הדפדפן.

השתמשו באותו bean באמצעות הזרקה לבנאי. אפשר להשתמש ב-RestClient ממספר תהליכונים, אבל כל בקשה חוסמת את התהליכון שקורא לה. אל תפעילו את המתודות האלה בלולאת אירועים של WebFlux. התיעוד של לקוחות REST ב-Spring מתאר את הלקוח הסינכרוני.

שכבת התעבורה משתמשת בזמן קצוב של 10 שניות להתחברות ובזמן קצוב של 25 שניות לקריאה, ללא הפניות. התגובות נקראות כמחרוזות ומפוענחות באמצעות Gson, ולא ממופות לאובייקטי תגובה מטיפוסים מוגדרים.

הגדרת האתר, הפעולה והפרוקסי

לפני הקריאה ל-create, הגדירו בסביבת העבודה פרופיל פעיל לאתר היעד. שליחת שם מארח ופעולה אינה יוצרת את הפרופיל הזה. ראו הגדרת פרופיל אתר אם האתר עדיין לא מוגדר.

  • העבירו את שם המארח בתור site, ולא כתובת URL מלאה של דף. בקשת reCAPTCHA אינה כוללת שדה url או type.
  • מחלקת העזר מקבעת את action לערך login. שנו את הערך הזה, או הפכו אותו לפרמטר של המתודה, אם הבקשה המיועדת משתמשת בפעולה אחרת.
  • העבירו כתובת URL אחת של פרוקסי. ה-API דורש בדיוק אחד מבין proxy או proxyCandidates; מחלקת העזר הזו מממשת את האפשרות של פרוקסי יחיד.
  • מחלקת העזר משמיטה את recaptchaType, ולכן ה-API משתמש בברירת המחדל שלו, enterprise-v3.

יצירה פעם אחת ותשאול באמצעות מזהה המשימה שנשמר

  1. 1.

    שמירת מזהה בקשה לפני היצירה

    בחרו requestId שמכיל 1–64 אותיות ASCII, ספרות, קווים תחתונים או מקפים. שמרו אותו יחד עם נתוני הקלט של המשימה לפני הקריאה ל-create. הוא מאפשר לשחזר את אותה משימה אם תגובת היצירה אבדה.

  2. 2.

    קריאה ל-create ושמירת ה-id שהוחזר

    קראו למתודה create של ה-bean עם שם המארח, הפרוקסי ומזהה הבקשה ששמרתם. היא שולחת בקשת POST אחת אל /v1/tasks עם waitMs=0. שמרו את ה-id שהוחזר; השתמשו במזהה המשימה הזה, ולא במזהה הבקשה, לשליפות הבאות.

  3. 3.

    קריאה ל-get עד שהמשימה מגיעה לסטטוס סופי

    העבירו ל-get את מזהה המשימה ששמרתם. כל שליפה מבקשת waitMs=15000 וחוסמת בזמן ההמתנה לתגובה. המשיכו כשהסטטוס הוא pending או solving, בכפוף למועד סיום שנקבע ברמת האפליקציה. עצרו כשהסטטוס הוא ready או failed. הזמנים הקצובים של HTTP מגבילים בקשות בודדות, ולא את לולאת התשאול כולה.

  4. 4.

    קריאת הפתרון רק כשהוא מוכן

    עבור reCAPTCHA, שלחו את solution.token ליעד המיועד — לא את מזהה המשימה. השתמשו ב-userAgent וב-secChUa שהוחזרו עם אותו פרוקסי שהצליח. אל תחליפו אותם בכותרות דפדפן לא קשורות ואל תשנו את כתובת ה-URL של היעד. משימה מוכנה מספקת פתרון; היא אינה מעידה שהיעד קיבל את הבקשה ששלחתם לאחר מכן.

טיפול בשגיאות HTTP בנפרד ממשימות שנכשלו

הזמן הקצוב לקריאת היצירה מסתיים לפני שמתקבל מזהה משימה.

ייתכן שהשרת יצר את המשימה אף שהלקוח שלכם לא קיבל את התגובה.

כדאי לנסות: לצורך שחזור, שלחו שוב את אותה בקשת משימה עם ה-requestId ששמרתם. נתוני קלט תואמים מחזירים את המשימה הקיימת. אל תיצרו מזהה בקשה חדש אלא אם בכוונתכם ליצור משימה לוגית חדשה.

קריאת get נכשלת בשכבת HTTP.

RestClient.retrieve() זורקת חריגה בתגובות HTTP שאינן מציינות הצלחה. אין פירוש הדבר שסטטוס המשימה הוא failed.

כדאי לנסות: טפלו בשגיאת HTTP לפני שתנסו לקרוא תוכן של תגובת הצלחה. שמרו את מזהה המשימה הידוע לצורך שחזור במקום ליצור משימה נוספת. אבחנו נתוני קלט לא תקינים לפני שתנסו לשלוח אותם שוב ללא שינוי.

תגובת המשימה מכילה סטטוס failed.

קראו את errorCode ואת error שלה; site-unreachable הוא אחד מקודי השגיאה האפשריים של משימה.

כדאי לנסות: הפסיקו לתשאל את המשימה וטפלו בגורם שדווח לפני שתתחילו משימה נוספת. ניתן החזר על ניסיונות פתרון שנכשלו; אל תניחו שהכישלון מעיד על יתרה לא מספקת.

שימוש חוזר במזהה בקשה גורם להתנגשות.

השוו את נתוני הקלט של המשימה החדשה לאלה שנשמרו עבור מזהה הבקשה הזה.

כדאי לנסות: השתמשו בנתוני הקלט המקוריים כדי לשחזר את המשימה הקיימת. השתמשו במזהה בקשה חדש עבור נתוני קלט ששונים במכוון.

לפירוש השגיאות, ראו שגיאות CAPTCHA API.

הפעלת המשימה הראשונה שלך.

התחילו עם $5 בקרדיט לסביבת העבודה.

יצירת סביבת עבודה
קריאה ל-API של CAPTCHA מתוך Spring Boot · solvethree