إرسال رمز CAPTCHA عبر وكيل HTTP في Go

بقلم solvethreeمدة القراءة: 3 دقيقة

استخدم عميل Go HTTP مستقلًا للموقع المستهدف، واضبطه بالوكيل الذي تحدده solvethree.SuccessfulProxy. أرسل Solution.Token باستخدام هوية المتصفح المُعادة. أبقِ طبقة النقل هذه الخاصة بالهدف منفصلة عن طبقة نقل API الخاصة بـ solvethree في عميل SDK.

في هذه الصفحة

إعداد المهمة

  1. 1.

    إعداد Go SDK وبيانات الاعتماد

    استخدم الوحدة الرسمية solvethree.com/sdk بالإصدار v0.1.0 مع Go 1.22 أو أحدث. تتوفر تفاصيل الإعداد في مرجع التكامل مع Go. اضبط SOLVETHREE_API_KEY على مفتاح API لمساحة عملك وأبقِه على الخادم. اضبط SOLVETHREE_PROXY على عنوان URL لوكيل HTTP أو HTTPS.

  2. 2.

    تهيئة الموقع قبل الحل

    تحتاج مساحة العمل إلى ملف تعريف نشط لاسم المضيف المستهدف. أعدّ ملف تعريف الموقع أولًا؛ إرسال اسم مضيف وإجراء لا ينشئ ملفًا.

  3. 3.

    استبدال الهدف في المثال

    غيّر accounts.example.com والإجراء login ونقطة نهاية التطبيق بما يلائم تكاملك. Site هو اسم مضيف، وليس عنوان URL كاملًا. في reCAPTCHA، حدّد واحدًا فقط من Proxy أو ProxyCandidates؛ ولا تملأ حقلَي Type أو URL في المهمة. النوع الافتراضي لـ reCAPTCHA هو Enterprise v3.

الإرسال عبر الوكيل الذي حل المهمة

Go · الإرسال عبر الوكيل الناجح
package main

import (
    "context"
    "fmt"
    "log"
    "os"
    "net/http"
    "net/url"
    "strings"
    "time"
    solvethree "solvethree.com/sdk"
)

func main() {
    client, err := solvethree.NewClient(os.Getenv("SOLVETHREE_API_KEY"), nil)
    if err != nil { log.Fatal(err) }
    ctx, cancel := context.WithTimeout(context.Background(), 180*time.Second)
    defer cancel()
    input := solvethree.TaskRequest{Site: "accounts.example.com", Action: "login", Proxy: os.Getenv("SOLVETHREE_PROXY")}
    result, err := client.Solve(ctx, input, solvethree.SolveOptions{})
    if err != nil { log.Fatal(err) }
    fmt.Println("Ready task:", result.ID)

    proxy, ok := solvethree.SuccessfulProxy(input, result)
    if !ok { log.Fatal("No valid successful proxy") }
    proxyURL, err := url.Parse(proxy)
    if err != nil { log.Fatal(err) }
    transport := http.DefaultTransport.(*http.Transport).Clone()
    transport.Proxy = http.ProxyURL(proxyURL)
    defer transport.CloseIdleConnections()
    targetClient := &http.Client{Transport: transport, Timeout: 30*time.Second,
        CheckRedirect: func(*http.Request, []*http.Request) error { return http.ErrUseLastResponse }}
    request, err := http.NewRequestWithContext(ctx, "POST", "https://accounts.example.com/login",
        strings.NewReader(url.Values{"g-recaptcha-response": {result.Solution.Token}}.Encode()))
    if err != nil { log.Fatal(err) }

    request.Header.Set("User-Agent", result.Solution.UserAgent)
    request.Header.Set("sec-ch-ua", result.Solution.SecChUA)
    request.Header.Set("Content-Type", "application/x-www-form-urlencoded")

    response, err := targetClient.Do(request)
    if err != nil { log.Fatal(err) }
    defer response.Body.Close()
    fmt.Println("Application HTTP status:", response.StatusCode)
    // Inspect the application response to determine whether submission succeeded.

}

تحل SDK المهمة لكنها لا ترسل أي شيء إلى الموقع. بعد الحل، ينسخ المثال http.DefaultTransport ويضبط Proxy في النسخة عبر http.ProxyURL. يستخدم targetClient المستقل وحده طبقة النقل تلك؛ وتبقى طبقة نقل API في عميل SDK دون تغيير.

أبقِ بيانات اعتماد الوكيل في مكوّن معلومات المستخدم ضمن عنوان URL. تحافظ url.Parse عليها لاستخدامها في طبقة نقل الوكيل. رمّز المحارف المحجوزة في اسم المستخدم أو كلمة المرور بالترميز المئوي بدلًا من تقسيم عنوان URL يدويًا أو إرسال بيانات اعتماد الوكيل ضمن ترويسة Authorization إلى الهدف.

احتفظ بمدخل المهمة الأصلي واستخدم SuccessfulProxy حتى إن كنت توفّر حاليًا وكيلًا واحدًا فقط. عند استخدام ProxyCandidates، يُحدَّد المرشح الناجح بواسطة Solution.EgressAttempts، وهو فهرس يبدأ من واحد في القائمة الأصلية. تجنّبك الدالة المساعدة تخمين المرشح الذي نجح؛ توقّف إذا أعادت false. تقبل قوائم المرشحين اثني عشر عنوان URL متميزًا لوكلاء HTTP أو HTTPS كحد أقصى، دون مسار أو استعلام أو جزء.

تضمين ترويسات الهدف وحقول النموذج والجلسة

يستخدم المثال url.Values لترميز Solution.Token بصيغة بيانات النماذج تحت الاسم g-recaptcha-response ويضبط نوع المحتوى المطابق. استبدل اسم الحقل هذا إذا كان تطبيقك يتوقع اسمًا آخر. أضف الحقول الأخرى التي تتطلبها نقطة النهاية، مثل مدخلات تسجيل الدخول وأي قيمة مضادة لـ CSRF مرتبطة بالجلسة؛ فرمز CAPTCHA ليس طلب تسجيل دخول كاملًا.

استخدم UserAgent وSecChUA المُعادين، كما يفعل المثال. إذا كان الحل يوفّر أيضًا عناصر في Headers، فطبّق تلك الترويسات المُعادة على الطلب إلى الهدف أيضًا؛ فالمثال لا ينسخ تلك المجموعة. حافظ على اتساق هوية المتصفح وصحة نوع المحتوى بالنسبة إلى متن الطلب الذي ترسله.

لا يحتوي المثال على مخزن لملفات تعريف الارتباط. إذا كان الهدف يتطلب جلسة، فأنشئ مخزنًا باستخدام net/http/cookiejar، وأرفقه بـ targetClient.Jar قبل بدء تدفق التعامل مع الهدف، وأعِد استخدام ذلك العميل لطلب الصفحة وإرسال النموذج. استخدم الوكيل الناجح نفسه طوال تلك الجلسة. عميل API الخاص بـ solvethree ليس عميل جلسة الهدف.

تحقق من خطأ الحل قبل الوصول إلى الحل. وحدها المهمة الجاهزة تتضمن حلاً صالحًا للاستخدام؛ ويوضح errorCode وerror في المهمة الفاشلة سبب فشلها. بالنسبة إلى الطلب الموجّه إلى الهدف، عالج الخطأ الناتج عن Do، ثم تحقق من حالة HTTP قبل تفسير نص الاستجابة. أغلق response.Body كلما أعاد Do استجابة دون خطأ، بما في ذلك استجابات HTTP غير الناجحة.

يعطّل المثال عمليات إعادة التوجيه التلقائية ويطبع حالة التطبيق. افحص نص الاستجابة وأي إعادة توجيه متوقعة لتحديد ما إذا كان التطبيق قد قبل الإرسال. جاهزية المهمة، أو حتى نجاح حالة HTTP وحده، لا تثبت هذه النتيجة.

شغّل مهمتك الأولى.

ابدأ برصيد قدره $5 في مساحة العمل.

إنشاء مساحة عمل
إرسال رمز CAPTCHA عبر وكيل HTTP في Go · solvethree