C# में Friendly Captcha कैसे हल करें (v1 और v2 widget)

C# में Friendly Captcha हल करने के लिए, FriendlyCaptchaAsync को sitekey, पेज URL और widget वर्ज़न के साथ कॉल करें, फिर token को उस फॉर्म फ़ील्ड में पोस्ट करें जिसकी उस वर्ज़न को ज़रूरत होती है। सारा खेल वर्ज़न का है। Friendly Captcha एक ही नाम के तहत दो अलग-अलग प्रोटोकॉल देता है, और दोनों एक ही sitekey namespace साझा करते हैं, इसलिए key में ऐसा कुछ नहीं होता जो बताए कि साइट कौन सा चलाती है। गलत वाला हल करें तो आपको सही ढंग से बना एक token मिलेगा, जिसे साइट बिना वजह बताए ठुकरा देती है। CapSkip ने Friendly Captcha को वर्ज़न 1.4.0 में जोड़ा। यह गाइड तीन चीज़ें कवर करती है: दोनों को अलग पहचानना, कॉल, और सबमिट।
आपको क्या चाहिए
- किसी Windows मशीन पर चल रहा CapSkip 1.4.0 या उसके बाद का संस्करण। Friendly Captcha सपोर्ट उसी रिलीज़ में आया था, CaptchaFox और Capy Puzzle के साथ।
- CapSkip .NET पैकेज का 1.3.0 या उसके बाद का वर्ज़न, यही वह रिलीज़ है जिसमें FriendlyCaptchaAsync जोड़ा गया। यह .NET Standard 2.0 को टारगेट करता है, इसलिए .NET Framework 4.6.1 और उससे ऊपर, .NET Core 2.0 और उससे ऊपर, तथा .NET 6 और उसके बाद के संस्करण, सभी पर काम करता है। सैंपल top-level statements इस्तेमाल करते हैं, इसलिए उन्हें .NET 6 या उसके बाद के संस्करण पर चलाएँ।
- टारगेट पेज से तीन वैल्यू: widget element पर लगा sitekey, खुद पेज का URL, और उस widget script का पता जिसे पेज लोड करता है। स्टेप 1 दिखाता है कि हर एक कहाँ मिलती है।
- सॉल्वर के लिए एक पता। Local मोड केवल उसी डिवाइस के लिए 127.0.0.1 पर जवाब देता है; Server मोड आपके नेटवर्क पते या पब्लिक IP पर सुनता है ताकि कोई दूसरी मशीन API के ज़रिए उसे कॉल कर सके। दोनों यहाँ मिलते हैं: कनेक्शन सेटिंग्स, और आपको कौन सा चाहिए, यह स्टेप 4 में बताया गया है।
# dotnet add package CapSkip dotnet add package CapSkip
स्टेप 1: Friendly Captcha v1 और v2 में फ़र्क पहचानें
दोनों वर्ज़न एक ही element रेंडर करते हैं: frc-captcha class वाला एक div, जिस पर data-sitekey attribute होता है। यानी element आपको बताता है कि sitekey कहाँ है, प्रोटोकॉल के बारे में कुछ नहीं। राज़ वह script टैग खोलता है जो widget को लोड करता है, क्योंकि v1 और v2 अलग-अलग फ़ाइल नामों वाले अलग-अलग पैकेज हैं।
| तुलना का बिंदु | वर्ज़न 1 | वर्ज़न 2 |
|---|---|---|
| पेज कौन सा पैकेज लोड करता है | friendly-challenge | @friendlycaptcha/sdk |
| स्क्रिप्ट फ़ाइल | widget.module.min.js, और fallback के रूप में widget.min.js | site.min.js, और fallback के रूप में site.compat.min.js |
| token किस फॉर्म फ़ील्ड में जाता है | frc-captcha-solution | frc-captcha-response |
| token कैसा दिखता है | डॉट से अलग किए गए चार हिस्से, कुछ सौ कैरेक्टर लंबा | एक ही opaque स्ट्रिंग जो AQQA और एक डॉट से शुरू होती है, लगभग छह किलोबाइट |
पेज का सोर्स देखें, element खोजने के लिए frc-captcha सर्च करें, फिर उसे लोड करने वाले script टैग पढ़ें। Friendly Captcha यही जाँच यहाँ बताता है: दोनों वर्ज़न पर उसका अपना पेज। अगर साइट widget को खुद होस्ट करती है, तो पैकेज का नाम URL से गायब हो सकता है, इसलिए उसकी जगह फ़ाइल नाम देखें। साइट की उम्र से अनुमान न लगाएँ: दोनों वर्ज़न लाइव हैं, और Friendly Captcha का कहना है कि वह v1 को कई सालों तक मेंटेन करता रहेगा।
स्टेप 2: FriendlyCaptchaAsync कॉल
एक method, तीन आर्गुमेंट: sitekey, पेज URL, और एक ऑप्शंस डिक्शनरी। स्टेप 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-responseversion ऑप्शन v1 या v2 लेता है, और सिर्फ़ 1 या 2 भी काम करता है। कोई और वैल्यू होने पर SDK रिक्वेस्ट भेजने से पहले ही ValidationException के साथ उसे मना कर देता है। यह जानबूझकर है: अनुमान से दिया गया वर्ज़न एक सही दिखने वाला token लौटाएगा जिसे साइट फेंक देगी, और यह एरर से भी बुरा है। हालाँकि null वर्ज़न को मना नहीं किया जाता। उसे हटा दिया जाता है, और सॉल्वर v1 पर लौट जाता है, जैसा नीचे बताया गया है।
Token प्रॉपर्टी पढ़ें। Code प्रॉपर्टी में भी वही स्ट्रिंग होती है, लेकिन Token का नाम उसी फ़ील्ड पर है जिसमें वह जाता है। user agent यहाँ null रहता है, क्योंकि सिर्फ़ Turnstile और CaptchaFox ही उसे रिपोर्ट करते हैं।
वर्ज़न का फ़ैसला script के पते पर छोड़ना
अगर आपके कोड के पास पहले से widget script का पता है, तो उसके बजाय वही पास करें, और CapSkip वर्ज़न उस build से पढ़ लेता है जिसे साइट असल में लोड करती है। इससे भरोसेमंद संकेत कोई नहीं। सॉल्वर एक तय क्रम में जाँच करता है और पहले जवाब पर रुक जाता है: पहले version ऑप्शन, फिर script का पता, फिर डिफ़ॉल्ट 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",
});अगर आपके पास fallback script है, तो nomodule_script ऑप्शन उसी के साथ यही काम करता है। हालाँकि उस क्रम के आख़िरी क़दम पर ध्यान दें। न वर्ज़न हो और न script का पता, तो सॉल्वर v1 मान लेता है, इसलिए सिर्फ़ sitekey के साथ हल की गई v2 साइट ठीक उसी तरह फेल होती है जिसकी चेतावनी यह पूरी गाइड देती है।
EU endpoint वाली साइटें
Friendly Captcha एक data residency विकल्प बेचता है जो puzzles सिर्फ़ जर्मनी से देता है। उस सर्विस पर चलने वाले v2 widget पर data-api-endpoint attribute होता है, जो आमतौर पर eu पर सेट रहता है, और जब आप इसे देखें, तो वही वैल्यू api_server ऑप्शन के रूप में पास करें। वह ऑप्शन global (जो डिफ़ॉल्ट है), eu, या पूरा URL लेता है। दोनों endpoint एक ही sitekey के लिए token बना देंगे, इसलिए यहाँ हुई गलती सिर्फ़ साइट के अपने वेरिफ़िकेशन में पकड़ी जाती है, और यह फिर से वही चुपचाप होने वाली नाकामी है।
स्टेप 3: token को सही फ़ील्ड में पोस्ट करें
फ़ील्ड का नाम दूसरी चीज़ है जो लोगों को उलझाती है, आमतौर पर ठीक तब जब कोई चलता हुआ v1 इंटीग्रेशन किसी v2 साइट पर लगा दिया जाता है। widget अपना token एक hidden input में लिखता है, और आपकी रिक्वेस्ट को भी उसे उसी जगह रखना होगा।
// 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);इसके ऊपर दो बातें और। साइट widget element पर एक attribute से फ़ील्ड का नाम बदल सकती है, v2 पर data-form-field-name और v1 पर data-solution-field-name, इसलिए इसे जाँचें और अगर यह मौजूद है तो इसकी वैल्यू इस्तेमाल करें। और कुछ इंटीग्रेशन token को फॉर्म पोस्ट के बजाय JSON बॉडी में भेजते हैं, इसलिए DevTools खोलें, फॉर्म को एक बार हाथ से सबमिट करें, और पेज जो भेजता है ठीक वैसा ही करें।
v2 के साथ साइज़ मायने रखता है। करीब छह किलोबाइट का token POST बॉडी में ठीक है, लेकिन यह किसी सर्वर की query string सीमा से आगे जा सकता है या किसी संकरे डेटाबेस कॉलम में कट सकता है, और कटा हुआ token वेरिफ़िकेशन में गलत token की तरह ही फेल होता है। इसे पूरा रखें और एक ही बार भेजें। Friendly Captcha का वेरिफ़िकेशन दोनों वर्ज़न में ऐसे response को ठुकरा देता है जो expire हो चुका हो या पहले इस्तेमाल हो चुका हो, इसलिए एक token सिर्फ़ एक सबमिट के लिए है और उसे फ़ौरन भेज देना चाहिए।
स्टेप 4: timeout, और सॉल्वर कहाँ चलता है
Friendly Captcha proof of work है, लेकिन मिलीसेकंड वाला नहीं। सर्विस हर रिक्वेस्ट के आते ही उसी पल तय करती है कि उस पर कितना काम लगना चाहिए, और जिन पतों को वह पहले बहुत देख चुकी है उनके लिए यह आँकड़ा बढ़ा देती है। CapSkip हर v2 widget को असली ब्राउज़र में भी हल करता है। इसलिए यह method डिफ़ॉल्ट timeout पर नहीं, बल्कि लंबे reCAPTCHA पोलिंग timeout पर चलता है।
| कंस्ट्रक्टर ऑप्शन | डिफ़ॉल्ट | यह क्या कवर करता है |
|---|---|---|
| recaptchaTimeout | 300 सेकंड | Friendly Captcha, CaptchaFox, reCAPTCHA और GeeTest की पोलिंग |
| defaultTimeout | 120 सेकंड | इमेज, ALTCHA और Capy की पोलिंग |
| pollingInterval | अधिकतम 5 सेकंड | पोलिंग 0.25 सेकंड से शुरू होती है और बढ़कर इस तक पहुँचती है |
अगर लंबे रन के दौरान solve धीमे होते जाएँ, तो इसकी संभावित वजह वही बढ़ती कठिनाई है, और ज़्यादा पते इसका इलाज हैं। यह method हर रिक्वेस्ट के लिए अलग प्रॉक्सी स्वीकार करता है, और CapSkip में कॉन्फ़िगर किया गया प्रॉक्सी पूल लोड को आपके लिए बाँट देता है। ज़्यादातर टाइप की तुलना में यहाँ ये दोनों जल्दी रख लेना फ़ायदेमंद है।
सैंपल 127.0.0.1 इस्तेमाल करते हैं, क्योंकि जब आपका कोड और सॉल्वर एक ही मशीन पर हों तो यही सही है। जैसे ही कॉल करने वाला कोड कहीं और चलने लगता है, जैसे किसी कंटेनर, बिल्ड एजेंट या VPS पर, loopback गलत मशीन की ओर इशारा करता है और पहला ही solve एक NetworkException फेंक देता है। CapSkip को Server मोड पर कर दें और वह इसके बजाय आपके नेटवर्क पते या पब्लिक IP पर सुनता है, ताकि इनमें से कोई भी API के ज़रिए उस तक पहुँच सके। अगर रास्ता इंटरनेट से होकर जाता है तो स्टैटिक पब्लिक IP इस्तेमाल करें, साथ में अपेक्षित पतों के लिए फ़ायरवॉल नियम रखें। यह अब भी आपका अपना हार्डवेयर है, और अब भी बिना मीटर वाला है।
क्लाइंट एनवायरनमेंट वेरिएबल खुद नहीं पढ़ता। CAPSKIP_HOST को अपने कोड में पढ़ें और उसे constructor को पास करें, जैसा पूरा उदाहरण करता है, ताकि एक ही build आपकी डेस्क पर भी चले और सर्वर पर भी।
पूरा चलने वाला उदाहरण
// 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");
}वर्ज़न एक बार तय होता है और दो बार इस्तेमाल होता है, solve के लिए और फ़ील्ड के नाम के लिए, इसलिए दोनों में कभी मतभेद नहीं हो सकता। जब regex को कुछ नहीं मिलता, तो आमतौर पर widget HTML में लिखे जाने के बजाय JavaScript से बनाया गया होता है, और आपको sitekey रेंडर हुए पेज से या उसे बनाने वाली script से पढ़नी होगी। इस method के पीछे का raw endpoint, और वह जो भी पैरामीटर स्वीकार करता है, सब यहाँ दर्ज है: API रेफ़रेंस, और पैकेज जो बाकी सभी method देता है, वे सब यहाँ सूचीबद्ध हैं: C# कैप्चा सॉल्वर पेज.
आम errors और उनका मतलब
| आप जो देखते हैं | कारण | फिक्स |
|---|---|---|
| साइट उस token को ठुकरा देती है जिसे CapSkip ने हल हुआ बताकर लौटाया था | गलत वर्ज़न हल हुआ, अक्सर v2 साइट पर डिफ़ॉल्ट v1 लागू हो गया | script टैग पढ़ें और वर्ज़न पास करें, या script का पता पास करें |
| वर्ज़न सही होने के बावजूद साइट token ठुकरा देती है | token दूसरे वर्ज़न के फ़ील्ड में चला गया, या साइट ने फ़ील्ड का नाम बदल दिया | उस वर्ज़न का फ़ील्ड इस्तेमाल करें, या v2 पर data-form-field-name में और v1 पर data-solution-field-name में दिया गया नाम |
| साइट token ठुकरा देती है और widget पर data-api-endpoint सेट है | साइट किसी क्षेत्रीय endpoint पर चलती है और solve में डिफ़ॉल्ट endpoint इस्तेमाल हुआ | attribute की वैल्यू को api_server ऑप्शन के रूप में पास करें |
| कुछ भी भेजे जाने से पहले ही ValidationException | sitekey या पेज URL खाली था, वर्ज़न v1, v2, 1 या 2 नहीं था, या ऑप्शंस में ऐसी key थी जो यह method नहीं लेता | जाँचें कि regex को element मिला, वर्ज़न की वैल्यू ठीक करें, और अनजान ऑप्शन हटा दें |
| डाउनलोड किए गए HTML में कोई frc-captcha element नहीं | पेज widget को JavaScript से बनाता है | sitekey रेंडर हुए पेज से या उसे बनाने वाली script से पढ़ें |
| एक बार चल चुका token दूसरे सबमिट पर फेल हो जाता है | Friendly Captcha हर response को एक ही बार स्वीकार करता है, और response expire हो जाते हैं | हर सबमिट के लिए नया solve करें, और तुरंत सबमिट करें |
| लंबे रन के साथ-साथ धीमे होते solve | सर्विस उस पते के लिए काम बढ़ा देती है जिसे वह बहुत देख चुकी है | solve को एक प्रॉक्सी पूल में बाँट दें |
| पहले solve पर एक NetworkException | CapSkip चल नहीं रहा, या host और port गलत हैं | CapSkip शुरू करें, फिर देखें कि उसे Local मोड में होना चाहिए या Server मोड में |
| build किसी अस्पष्ट TimeoutException पर फ़ेल हो जाता है | CapSkip और System, दोनों उस छोटे नाम को परिभाषित करते हैं | पूरा CapSkip.TimeoutException लिखें, या CapSkipError कैच करें |
FAQ
क्या C# में Friendly Captcha हल करने के लिए मेरी तरफ़ ब्राउज़र चाहिए?
नहीं। आपके कोड को एक HttpClient चाहिए, और कुछ नहीं। CapSkip काम उसी मशीन पर करता है जिस पर वह चलता है, और v2 के लिए इसका मतलब है वहीं एक असली ब्राउज़र में widget चलाना, और यही एक वजह है कि यह method लंबा timeout इस्तेमाल करता है। आपकी तरफ़ से एक sitekey, एक URL और एक वर्ज़न जाता है, और बदले में पोस्ट करने के लिए एक स्ट्रिंग मिलती है, इसलिए यह किसी वर्कर सर्विस या शेड्यूल्ड जॉब के अंदर आराम से चलता है।
यह ALTCHA हल करने से कैसे अलग है?
दोनों proof of work हैं, और समानता यहीं खत्म हो जाती है। ALTCHA में आप challenge या वह endpoint देते हैं जहाँ से वह आता है, हैशिंग में मिलीसेकंड लगते हैं, और method 120 सेकंड के डिफ़ॉल्ट timeout पर चलता है। Friendly Captcha में सर्विस हर रिक्वेस्ट के लिए कठिनाई तय करती है और व्यस्त पतों के लिए उसे बढ़ा देती है, v2 ब्राउज़र में हल होता है, और method 300 सेकंड के timeout पर चलता है। साथ ही ALTCHA में एक फ़ील्ड नाम है, जबकि Friendly Captcha में दो। ALTCHA वाला पहलू यहाँ कवर किया गया है: C# ALTCHA गाइड.
क्या किसी होस्टेड प्लेटफ़ॉर्म पर चल रहा .NET ऐप solver तक पहुँच सकता है?
हाँ। कनेक्शन सेटिंग्स में CapSkip को Server मोड पर कर दें ताकि वह loopback के बजाय किसी नेटवर्क पते पर सुने, वह पता अपने कोड में CAPSKIP_HOST से पढ़ें, और उसे क्लाइंट को पास करें। कंटेनर होस्ट, VPS, CI एजेंट और मैनेज्ड ऐप सर्विस, सब उसी तरह जुड़ते हैं, उसी HTTP API के ज़रिए। अगर रास्ता इंटरनेट से होकर जाता है तो फ़ायरवॉल नियम के साथ स्टैटिक पब्लिक IP इस्तेमाल करें। सॉल्वर आपके अपने हार्डवेयर पर ही रहता है, इसलिए लाइसेंस या हल की गिनती में कुछ नहीं बदलता।
क्या मैं tokens का एक बैच पहले से हल करके रख सकता हूँ?
रख तो सकते हैं, पर उसका कोई फ़ायदा नहीं। हर response एक ही बार स्वीकार होता है और expire हो जाता है, और Friendly Captcha इन दोनों मामलों को साइट को नाकामी के रूप में रिपोर्ट करता है। जमा किया गया भंडार नामंज़ूरियों के ढेर में बदल जाता है। तभी हल करें जब आप सबमिट करने ही वाले हों, और इसके बजाय काम concurrency से करवाएँ: क्लाइंट async है, इसलिए कई solve पर एक Task.WhenAll उन्हें साथ-साथ चलाता है।
संक्षेप में
C# में Friendly Captcha हल करने के लिए, widget script खोजें, उससे v1 या v2 तय करें, और वह वर्ज़न sitekey और पेज URL के साथ FriendlyCaptchaAsync को दें। token को v1 के लिए frc-captcha-solution में या v2 के लिए frc-captcha-response में रखें, जब तक कि साइट ने फ़ील्ड का नाम न बदला हो, और उसे एक बार, तुरंत भेजें। अगर widget EU endpoint इस्तेमाल करता है तो आप भी वही endpoint दें, उम्मीद रखें कि solve में मिलीसेकंड नहीं बल्कि सेकंड लगेंगे, और जैसे ही कॉल करने वाला कोड सॉल्वर की मशीन से बाहर जाए, Server मोड पर चले जाएँ।
- यह टाइप कैसे काम करता है और सॉल्वर क्या-क्या कवर करता है: Friendly Captcha सॉल्वर पेज.
- .NET पैकेज जो बाकी सभी method देता है: C# और .NET सॉल्वर पेज.
एक आख़िरी बात, जो तय करती है कि आप दोबारा कोशिश कैसे करेंगे। जब कोई token ठुकराया हुआ लौटता है, तो ईमानदार इलाज लगभग हमेशा सही वर्ज़न के साथ एक नया solve ही होता है, और लोकल captcha सॉल्वर के साथ वह दोबारा कोशिश उस मशीन पर बस कुछ सेकंड लेती है जो पहले से आपकी है, न कि किसी के बिल में एक और लाइन जोड़ती है।
