Cara Memecahkan Friendly Captcha di C# (Widget v1 dan v2)

solve friendly captcha in c# - How to Solve Friendly Captcha in C# (v1 and v2 Widgets)

Untuk memecahkan Friendly Captcha di C#, panggil FriendlyCaptchaAsync dengan sitekey, URL halaman, dan versi widget, lalu kirim token ke field form yang diharapkan versi tersebut. Versi adalah inti dari seluruh pekerjaan ini. Friendly Captcha menghadirkan dua protokol berbeda dengan satu nama, dan keduanya berbagi satu ruang nama sitekey, sehingga tidak ada apa pun pada sitekey yang memberi tahu Anda versi mana yang dijalankan sebuah situs. Jika Anda memecahkan versi yang salah, Anda mendapat token yang formatnya benar tetapi ditolak situs tanpa penjelasan. CapSkip menambahkan Friendly Captcha pada versi 1.4.0. Panduan ini membahas cara membedakan keduanya, pemanggilannya, dan pengirimannya.

Apa yang Anda butuhkan

  • CapSkip 1.4.0 atau lebih baru yang berjalan di komputer Windows. Dukungan Friendly Captcha hadir pada rilis tersebut, bersama CaptchaFox dan Capy Puzzle.
  • Paket CapSkip .NET versi 1.3.0 atau lebih baru, yaitu rilis yang menambahkan FriendlyCaptchaAsync. Paket ini menargetkan .NET Standard 2.0, jadi .NET Framework 4.6.1 ke atas, .NET Core 2.0 ke atas, dan .NET 6 serta yang lebih baru semuanya bisa dipakai. Contoh kodenya memakai top-level statements, jadi jalankan di .NET 6 atau lebih baru.
  • Tiga nilai dari halaman target: sitekey pada elemen widget, URL halaman itu sendiri, dan alamat skrip widget yang dimuat halaman tersebut. Langkah 1 menunjukkan letak masing-masing.
  • Sebuah alamat untuk pemecah CAPTCHA. Mode Local menjawab di 127.0.0.1 hanya untuk perangkat itu; mode Server mendengarkan di alamat jaringan atau IP publik Anda sehingga mesin lain dapat memanggilnya melalui API. Keduanya ada di pengaturan koneksi, dan Langkah 4 membahas mana yang Anda butuhkan.
# dotnet add package CapSkip
dotnet add package CapSkip

Langkah 1: bedakan Friendly Captcha v1 dari v2

Kedua versi merender elemen yang sama, yaitu sebuah div dengan class frc-captcha dan atribut data-sitekey. Jadi elemen itu memberi tahu Anda di mana sitekey berada, tetapi tidak memberi tahu apa pun tentang protokolnya. Yang membocorkannya adalah tag script yang memuat widget, karena v1 dan v2 adalah paket berbeda dengan nama file yang berbeda.

Yang dibandingkanVersi 1Versi 2
Paket yang dimuat halamanfriendly-challenge@friendlycaptcha/sdk
File skripwidget.module.min.js, dengan widget.min.js sebagai cadangansite.min.js, dengan site.compat.min.js sebagai cadangan
Field form tempat token dimasukkanfrc-captcha-solutionfrc-captcha-response
Bentuk tokenEmpat bagian yang dipisahkan titik, panjangnya beberapa ratus karakterSatu string opaque yang diawali AQQA dan sebuah titik, kira-kira enam kilobyte

Lihat kode sumber halaman, cari frc-captcha untuk menemukan elemennya, lalu baca tag script yang memuatnya. Friendly Captcha mendokumentasikan pemeriksaan yang sama di halaman mereka sendiri tentang kedua versi tersebut. Jika situs meng-host widget-nya sendiri, nama paket bisa hilang dari URL, jadi berpeganglah pada nama file. Jangan menebak dari usia situsnya: kedua versi masih aktif, dan Friendly Captcha menyatakan akan terus memelihara v1 selama beberapa tahun.

Langkah 2: pemanggilan FriendlyCaptchaAsync

Satu metode, tiga argumen: sitekey, URL halaman, dan sebuah dictionary opsi. Berikan versi yang Anda temukan di Langkah 1.

// dotnet add package CapSkip
using CapSkip;

var solver = new CapSkipClient(host: "127.0.0.1", port: 8080);

// Tell the solver which protocol the site runs.
var result = await solver.FriendlyCaptchaAsync(
    "YOUR_SITEKEY",
    "https://example.com/signup",
    new Dictionary<string, object?> { ["version"] = "v2" });

Console.WriteLine(result.Token);   // goes in frc-captcha-response

Opsi version menerima v1 atau v2, dan angka 1 atau 2 saja juga bisa. SDK menolak nilai lain dengan ValidationException sebelum permintaan apa pun dibuat. Itu memang disengaja: tebakan akan kembali sebagai token yang tampak valid tetapi dibuang oleh situs, dan itu lebih buruk daripada error. Namun, version yang bernilai null tidak ditolak. Nilai itu diabaikan, dan pemecah CAPTCHA kembali ke v1 seperti dijelaskan di bawah.

Baca properti Token. Properti Code membawa string yang sama, tetapi Token dinamai sesuai field tujuannya. User agent tetap null di sini, karena hanya Turnstile dan CaptchaFox yang melaporkannya.

Membiarkan alamat skrip menentukan versi

Jika kode Anda sudah memegang alamat skrip widget, berikan alamat itu sebagai gantinya, dan CapSkip akan membaca versinya dari build yang benar-benar dimuat situs, yang merupakan sinyal paling andal yang ada. Pemecah CAPTCHA memeriksa dengan urutan tetap dan berhenti pada jawaban pertama: opsi version, lalu alamat skrip, lalu default v1.

// Instead of the call above: copy the src straight off the page's module script tag.
var result = await solver.FriendlyCaptchaAsync(
    "YOUR_SITEKEY",
    "https://example.com/signup",
    new Dictionary<string, object?>
    {
        ["module_script"] =
            "https://cdn.jsdelivr.net/npm/@friendlycaptcha/[email protected]/site.min.js",
    });

Opsi nomodule_script melakukan tugas yang sama dengan skrip cadangan, jika itu yang Anda punya. Namun, perhatikan langkah terakhir dari urutan itu. Tanpa version maupun alamat skrip, pemecah CAPTCHA menganggapnya v1, sehingga situs v2 yang dipecahkan hanya dengan sitekey akan gagal persis seperti yang diperingatkan seluruh panduan ini.

Situs di endpoint EU

Friendly Captcha menjual opsi residensi data yang menyajikan puzzle hanya dari Jerman. Widget v2 pada layanan itu membawa atribut data-api-endpoint, biasanya bernilai eu, dan ketika Anda melihatnya, berikan nilai yang sama sebagai opsi api_server. Opsi itu menerima global (default-nya), eu, atau URL lengkap. Kedua endpoint akan menerbitkan token untuk sitekey yang sama, jadi kesalahan di sini hanya ketahuan lewat verifikasi milik situs itu sendiri, dan itu lagi-lagi jenis kegagalan yang diam-diam.

Langkah 3: kirim token ke field yang benar

Nama field adalah hal kedua yang sering menjebak orang, biasanya tepat setelah integrasi v1 yang sudah berjalan diarahkan ke situs v2. Widget menulis tokennya ke input tersembunyi, dan permintaan Anda harus menaruhnya di tempat yang sama.

// version holds what you passed in Step 2; http is your HttpClient.
// v1 reads frc-captcha-solution, v2 reads frc-captcha-response.
var isV2 = version is "v2" or "V2" or "2";
var field = isV2 ? "frc-captcha-response" : "frc-captcha-solution";

var body = new FormUrlEncodedContent(new Dictionary<string, string>
{
    ["email"] = "[email protected]",
    [field] = result.Token!,
});

var response = await http.PostAsync("https://example.com/signup", body);

Ada dua detail tambahan. Situs bisa mengganti nama field dengan atribut pada elemen widget, data-form-field-name di v2 dan data-solution-field-name di v1, jadi periksa atribut itu dan pakai nilainya jika ada. Selain itu, sebagian integrasi mengirim token di body JSON, bukan lewat form post, jadi buka DevTools, kirim form sekali secara manual, lalu tiru persis apa yang dikirim halaman itu.

Ukuran penting pada v2. Token sekitar enam kilobyte tidak masalah di body POST, tetapi bisa melampaui batas query string server atau terpotong oleh kolom database yang sempit, dan token yang terpotong gagal verifikasi sama seperti token yang salah. Jaga agar tetap utuh dan kirim sekali saja. Verifikasi Friendly Captcha menolak respons yang sudah kedaluwarsa atau sudah pernah dipakai, di kedua versi, jadi satu token hanya berlaku untuk satu pengiriman dan harus segera dikirim.

Langkah 4: timeout, dan di mana pemecah CAPTCHA berjalan

Friendly Captcha adalah proof of work, tetapi bukan jenis yang selesai dalam hitungan milidetik. Layanan itu menentukan seberapa banyak kerja yang layak untuk setiap permintaan pada saat permintaan itu dibuat, dan menaikkan angka tersebut untuk alamat yang sudah sering dilihatnya. CapSkip juga memecahkan setiap widget v2 di browser sungguhan. Jadi metode ini berjalan pada timeout polling reCAPTCHA yang lebih panjang, bukan timeout default.

Opsi constructorBawaanApa yang dicakupnya
recaptchaTimeout300 detikPolling Friendly Captcha, CaptchaFox, reCAPTCHA dan GeeTest
defaultTimeout120 detikPolling gambar, ALTCHA dan Capy
pollingIntervalMaksimum 5 detikPolling dimulai pada 0,25 detik dan melambat hingga nilai ini

Jika pemecahan makin lambat selama proses yang panjang, kenaikan tingkat kesulitan itulah penyebab yang paling mungkin, dan menambah alamat adalah solusinya. Metode ini menerima proxy per permintaan, dan pool proxy yang dikonfigurasi di CapSkip menyebarkan bebannya untuk Anda. Di sini keduanya layak disiapkan lebih awal dibanding pada kebanyakan tipe lain.

Contoh kode memakai 127.0.0.1 karena itu benar ketika kode Anda dan pemecah CAPTCHA berada di mesin yang sama. Begitu kode pemanggil berjalan di tempat lain, seperti container, build agent atau VPS, loopback menunjuk ke mesin yang salah dan pemecahan pertama melempar NetworkException. Alihkan CapSkip ke mode Server dan ia akan mendengarkan di alamat jaringan atau IP publik Anda, sehingga semua lingkungan itu dapat menjangkaunya melalui API. Gunakan IP publik statis jika rutenya melewati internet, dengan aturan firewall untuk alamat yang Anda harapkan. Perangkatnya tetap milik Anda, dan tetap tanpa kuota.

Klien tidak membaca variabel lingkungan dengan sendirinya. Baca CAPSKIP_HOST di kode Anda sendiri dan berikan ke konstruktor, seperti pada contoh lengkap, agar satu build bisa bekerja di komputer Anda maupun di server.

Contoh lengkap yang berfungsi

// dotnet add package CapSkip
using System.Text.RegularExpressions;
using CapSkip;

var pageUrl = "https://example.com/signup";
var http = new HttpClient();
var solver = new CapSkipClient(
    host: Environment.GetEnvironmentVariable("CAPSKIP_HOST") ?? "127.0.0.1",
    port: 8080);

// Read the sitekey off the widget element, in either attribute order.
var html = await http.GetStringAsync(pageUrl);
var widget = Regex.Match(html,
    "<[^>]*class=\"(?:[^\"]*\\s)?frc-captcha(?:\\s[^\"]*)?\"[^>]*>").Value;
var sitekey = Regex.Match(widget, "data-sitekey=\"([^\"]+)\"").Groups[1].Value;

// The package name in the script URL decides the version.
var v2 = html.Contains("@friendlycaptcha/sdk");
var v1 = html.Contains("friendly-challenge");
if (v1 == v2)
    throw new InvalidOperationException("Read the script tag and set the version by hand.");
var version = v2 ? "v2" : "v1";

try
{
    var result = await solver.FriendlyCaptchaAsync(sitekey, pageUrl,
        new Dictionary<string, object?> { ["version"] = version });

    // A site can rename the field on the widget element.
    var renamed = Regex.Match(widget,
        "data-(?:form|solution)-field-name=\"([^\"]+)\"").Groups[1].Value;
    var field = renamed.Length > 0 ? renamed
        : v2 ? "frc-captcha-response" : "frc-captcha-solution";
    var body = new FormUrlEncodedContent(new Dictionary<string, string>
    {
        ["email"] = "[email protected]",
        [field] = result.Token!,
    });

    // Post wherever the form's action attribute points.
    var response = await http.PostAsync(pageUrl, body);
    Console.WriteLine($"{(int)response.StatusCode} with a {version} token");
}
catch (CapSkip.ValidationException ex)
{
    // An empty sitekey or an unknown version, refused before any request.
    Console.WriteLine($"not sent: {ex.Message}");
}
catch (CapSkip.TimeoutException)
{
    Console.WriteLine("gave up waiting; recaptchaTimeout is 300 seconds");
}

Versi ditentukan sekali dan dipakai dua kali, untuk pemecahan dan untuk nama field, sehingga keduanya tidak akan pernah bertentangan. Ketika regex tidak menemukan apa pun, biasanya widget dibangun dari JavaScript alih-alih ditulis di dalam HTML, dan Anda perlu membaca sitekey dari halaman yang sudah dirender atau dari skrip yang membuatnya. Endpoint mentah di balik metode ini, beserta setiap parameter yang diterimanya, didokumentasikan di referensi API, dan setiap metode lain yang disediakan paket ini tercantum di halaman pemecah CAPTCHA C#.

Kesalahan umum dan artinya

Apa yang Anda lihatPenyebabPerbaiki
Situs menolak token yang dikembalikan CapSkip sebagai berhasil dipecahkanVersi yang dipecahkan salah, sering kali default v1 yang diterapkan ke situs v2Baca tag script lalu berikan versinya, atau berikan alamat skripnya
Situs menolak token padahal versinya sudah benarToken masuk ke field milik versi yang lain, atau situs mengganti nama field-nyaPakai field untuk versi itu, atau nama di data-form-field-name pada v2 atau data-solution-field-name pada v1
Situs menolak token dan widget memiliki atribut data-api-endpointSitus berjalan di endpoint regional dan pemecahan memakai endpoint defaultBerikan nilai atribut itu sebagai opsi api_server
ValidationException sebelum apa pun terkirimSitekey atau URL halaman kosong, versinya bukan v1, v2, 1 atau 2, atau opsi berisi key yang tidak diterima metode iniPastikan regex menemukan elemennya, perbaiki nilai version, dan buang opsi yang tidak dikenal
Tidak ada elemen frc-captcha di HTML yang Anda unduhHalaman membuat widget dari JavaScriptBaca sitekey dari halaman yang sudah dirender atau dari skrip yang membangunnya
Token yang berhasil sekali gagal pada pengiriman keduaFriendly Captcha menerima setiap respons hanya sekali, dan respons bisa kedaluwarsaPecahkan ulang untuk setiap pengiriman, dan langsung kirim
Pemecahan yang makin lambat seiring berjalannya proses yang panjangLayanan itu menaikkan beban kerja untuk alamat yang sudah sering dilihatnyaSebarkan pemecahan ke pool proxy
NetworkException pada pemecahan pertamaCapSkip tidak berjalan, atau host dan port-nya salahJalankan CapSkip, lalu periksa apakah ia harus berada di mode Local atau mode Server
Build gagal karena TimeoutException yang ambiguCapSkip dan System sama-sama mendefinisikan nama pendek ituTulis CapSkip.TimeoutException secara lengkap, atau tangkap CapSkipError

FAQ

Apakah saya butuh browser di sisi saya untuk memecahkan Friendly Captcha di C#?

Tidak. Kode Anda hanya butuh HttpClient, tidak lebih. CapSkip mengerjakannya di mesin tempat ia berjalan, dan untuk v2 itu berarti menjalankan widget di browser sungguhan di sana, yang menjadi salah satu alasan metode ini memakai timeout yang lebih panjang. Sisi Anda mengirim sitekey, URL dan versi, lalu menerima string untuk dikirim, sehingga kode Anda berjalan nyaman di dalam worker service atau scheduled job.

Apa bedanya dengan memecahkan ALTCHA?

Keduanya proof of work, dan kemiripannya berhenti di situ. Dengan ALTCHA, Anda menyerahkan challenge atau endpoint asalnya, hashing-nya hanya memakan milidetik, dan metodenya berjalan pada timeout default 120 detik. Dengan Friendly Captcha, layanan menetapkan tingkat kesulitan per permintaan dan menaikkannya untuk alamat yang sibuk, v2 dipecahkan di browser, dan metodenya berjalan pada timeout 300 detik. ALTCHA juga hanya punya satu nama field, sedangkan Friendly Captcha punya dua. Sisi ALTCHA dibahas di panduan ALTCHA C#.

Bisakah aplikasi .NET di platform hosting menjangkau pemecah CAPTCHA?

Bisa. Alihkan CapSkip ke mode Server di pengaturan koneksi agar ia mendengarkan di alamat jaringan, bukan di loopback, baca alamat itu dari CAPSKIP_HOST di kode Anda, lalu berikan ke klien. Container host, VPS, CI agent dan layanan aplikasi terkelola semuanya terhubung dengan cara yang sama, melalui API HTTP yang sama. Gunakan IP publik statis dengan aturan firewall jika rutenya melewati internet. Pemecah CAPTCHA tetap berada di perangkat milik Anda, jadi tidak ada yang berubah soal lisensi atau jumlah pemecahan.

Bisakah saya memecahkan sekumpulan token lebih dulu?

Tidak ada gunanya. Setiap respons hanya diterima sekali dan bisa kedaluwarsa, dan Friendly Captcha melaporkan kedua kasus itu ke situs sebagai kegagalan. Stok token hanya akan berubah menjadi tumpukan penolakan. Pecahkan saat Anda hendak mengirim, dan biarkan konkurensi yang bekerja: klien ini async, jadi Task.WhenAll atas beberapa pemecahan menjalankan semuanya secara berdampingan.

Versi singkatnya

Untuk memecahkan Friendly Captcha di C#, temukan skrip widget, tentukan v1 atau v2 darinya, dan berikan versi itu ke FriendlyCaptchaAsync bersama sitekey dan URL halaman. Masukkan token ke frc-captcha-solution untuk v1 atau frc-captcha-response untuk v2, kecuali situs mengganti nama field-nya, lalu kirim sekali saja, secepatnya. Sesuaikan dengan endpoint EU jika widget memakainya, bersiaplah pemecahan memakan hitungan detik alih-alih milidetik, dan beralihlah ke mode Server begitu kode pemanggil tidak lagi berada di mesin pemecah CAPTCHA.

Satu hal terakhir yang menentukan cara Anda mencoba ulang. Ketika token ditolak, perbaikan yang sebenarnya hampir selalu berupa pemecahan baru dengan versi yang benar, dan percobaan ulang itu dikerjakan oleh pemecah captcha lokal di mesin yang sudah Anda miliki, jadi biayanya hanya beberapa detik, bukan satu baris tambahan di tagihan orang lain.