如何在 C# 中识别 reCAPTCHA v3 Enterprise(.NET SDK)

在 C# 中识别 reCAPTCHA v3 Enterprise 使用的方法与其他所有 reCAPTCHA 类型相同。没有 RecaptchaEnterpriseAsync。你要调用 RecaptchaAsync 并传入两个标志: version 设为 v3,以及 enterprise 设为 1。漏掉任何一个,你都会得到一个针对不同产品的 token,网站会拒绝它。
下面是完整的调用、 action 选项的实际作用,以及如何判断你面对的是哪种变体。
version 和 enterprise 是相互独立的标志
这一点几乎所有人第一次都会搞混。Enterprise 不是 reCAPTCHA 的第四个版本。它是 Google 的另一个产品层级,同时运行 v2 和 v3,因此这两个设置构成一个真正的 2×2 组合。
| 网站运行的类型 | 你传入的选项 |
|---|---|
| reCAPTCHA v2 复选框 | 无 |
| reCAPTCHA v2 Enterprise | enterprise = 1 |
| reCAPTCHA v3 | version = "v3" |
| reCAPTCHA v3 Enterprise | version = "v3" 和 enterprise = 1 |
单独传入 enterprise = 1 会让你得到一个 v2 Enterprise 的识别结果,它在 v3 页面上会失败。这是 token 返回正常却随后被拒绝的最常见原因。
如何判断页面是否为 Enterprise
打开页面源代码,查看脚本调用的是哪个对象。标准 reCAPTCHA 使用 grecaptcha。Enterprise 使用 grecaptcha.enterprise.
// Enterprise pages call grecaptcha.enterprise, not grecaptcha.
// The action name you need is right here in execute().
grecaptcha.enterprise.ready(function () {
grecaptcha.enterprise.execute("YOUR_SITEKEY", { action: "login" })
.then(function (token) {
// token gets posted with the form
});
});还有两个迹象:脚本标签加载 /recaptcha/enterprise.js 而不是 /recaptcha/api.js,而 Enterprise 的 sitekey 通常以 6L 开头,和标准的一样,因此 key 本身说明不了什么。要相信脚本,而不是 key。
设置
CapSkip 在你自己的机器上运行,因此在这一切生效之前请先启动应用,然后从 NuGet 安装 SDK:
# .NET Standard 2.0,因此支持 .NET Framework 4.6.1+、Core 2.0+ # 以及所有现代 .NET 版本。 dotnet add package CapSkip
将客户端指向应用中显示的端口:
using CapSkip;
var solver = new CapSkipClient(
apiKey: "capskip", // any string when key validation is off
host: "127.0.0.1",
port: 8080,
recaptchaTimeout: 300); // seconds; v3 rarely gets near thisv3 Enterprise 调用
除 sitekey 和 URL 之外的所有内容都放在一个选项字典中:
using System.Collections.Generic;
using CapSkip;
var result = await solver.RecaptchaAsync(
"YOUR_SITEKEY",
"https://example.com/page-with-recaptcha",
new Dictionary<string, object?>
{
["version"] = "v3",
["enterprise"] = 1,
["action"] = "login", // match the page exactly
});
Console.WriteLine(result.Code); // g-recaptcha-response token签名为 RecaptchaAsync(string sitekey, string url, Dictionary<string, object?>? options = null)。该字典的值可为 null,因此 object? 如果你的项目启用了可空引用类型,这一点很重要。
action 选项的实际作用
action 仅用于 v3。在 v2 页面上它不起任何作用。
它是页面传给 grecaptcha.enterprise.execute()的标签。Google 会分别为每个 action 打分,网站后端通常会检查验证响应中的 action 是否与预期一致。如果页面写的是 login 而你用默认值去识别,那么你的 token 虽然有效却仍会被丢弃。请一字不差地复制该字符串,包括大小写。Google 将 action 限制为字母数字、斜杠和下划线,因此没有什么特殊字符需要转义。
出错时是静默的。不会报任何错,因为识别一侧没有任何问题。你只会得到一个被端点拒绝的 token。
没有最低分数选项
有必要直说,因为有些识别 API 会以此为卖点:你无法要求 CapSkip 返回某个特定分数的 token。分数是 Google 的判断,在你的目标站点验证 token 时给出,识别请求上没有任何参数能为它设定下限。如果你见过某个 min_score 字段,并在这里寻找对应项,那这就是你找不到它的原因。
提交 token
token 会写入页面提交的字段,通常是 g-recaptcha-response:
using System.Net.Http;
using var http = new HttpClient();
var form = new FormUrlEncodedContent(new[]
{
new KeyValuePair<string, string>(
"g-recaptcha-response", result.Code),
new KeyValuePair<string, string>("username", "demo"),
});
var response = await http.PostAsync(
"https://example.com/login", form);有一样东西你在这里不需要: result.UserAgent。它仅对 Turnstile 有值,对每一次 reCAPTCHA 识别都为 null。如果你从 Turnstile 代码复制了辅助函数,请去掉那个响应头,而不要发送 null。
reCAPTCHA token 同样是短命的。Google 会在两分钟后使其过期,因此请在你准备提交的那一刻识别,而不是在一长串工作流程的开头。
那 v2 Enterprise 呢?
相同的方法,不同的选项。去掉 version 和 action,并添加 datas 如果 Google 给页面提供了一个 data-s 值:
var v2 = await solver.RecaptchaAsync(sitekey, pageUrl,
new Dictionary<string, object?>
{
["enterprise"] = 1,
["datas"] = "YOUR_DATA_S_VALUE",
});data-s 出现在 Google 自家的产品上,几乎别无他处。如果你在页面中找不到它,就不需要它。
处理失败
每个 SDK 异常都派生自 CapSkipError。在编写 catch 块之前,有一个 .NET 陷阱值得了解。
using System;
using CapSkip;
try
{
var result = await solver.RecaptchaAsync(sitekey, pageUrl, options);
}
catch (CapSkip.ValidationException) { /* bad parameters */ }
catch (NetworkException) { /* CapSkip is not running */ }
catch (ApiException) { /* API returned an error */ }
catch (CapSkip.TimeoutException) { /* exceeded recaptchaTimeout */ }
catch (CapSkipError) { /* anything else from the SDK */ }TimeoutException 和 ValidationException 在两个命名空间中都存在 System 和 CapSkip。同时导入两个命名空间时,未限定的 catch 会解析为 System 类型,然后悄无声息地永不触发。请对它们加以限定,或者捕获 CapSkipError 并检查它。
常见错误
| 代码 | 原因 | 修复 |
|---|---|---|
ERROR_GOOGLEKEY | Sitekey 为空或格式错误 | 请从实时页面重新读取,而不是从缓存副本读取 |
ERROR_PAGEURL | URL 缺失或不是完整的绝对 URL | 请包含协议头(scheme),并使用小组件所在的页面 |
ERROR_BAD_PARAMETERS | 某个选项值的类型错误 | 校验 enterprise 是数字 1,而不是字符串 “1” |
ERROR_CAPTCHA_UNSOLVABLE | 识别未能完成 | 请确认版本标志与页面一致,然后在相同的网络路径上添加代理 |
每种类型的完整参数列表见 API 文档.
常见问题
Enterprise 是否有单独的方法?
没有。 RecaptchaAsync 可处理全部四种组合。Enterprise 只是选项字典中的一个标志,它与 version 配合使用,而不是替代它。
如果我把 action 名称写错了会怎样?
你会得到一个完全有效但被网站拒绝的 token。Google 在验证时会将 action 与分数一并返回,大多数后端会将其与预期值进行比较。识别工具不会报错,因为识别端并没有出错。
v3 Enterprise 需要代理吗?
仅当网站对地理位置敏感,或分数取决于请求 IP 时才需要。传入 ["proxy"] = new Proxy("HTTPS", "user:[email protected]:3128") 到同一个选项字典中。reCAPTCHA、Turnstile 和极验(GeeTest)支持代理,但图片验证码不支持。
我可以一次识别多个页面吗?
可以。每个方法都会返回一个 Task,因此 await Task.WhenAll(...) 就是你所需要的全部。SDK 还导出了 AsyncCapSkip ,但在 .NET 中它只是 CapSkipClient的别名,保留它是为了让从 Python SDK 移植过来的代码仍能编译。它没有任何额外作用。
小结
一个方法,两个标志。设置 version 设置为 v3 和 enterprise 设置为 1,把 action 从页面上一字不差地复制下来,然后提交 result.Code ,务必在两分钟内完成。没有需要调整的分数,因此如果 token 被拒,请先检查 action 和这些标志。
.NET 的其余接口见 C# 验证码识别 页面, Enterprise 支持 涵盖了其他语言,而 reCAPTCHA v3 识别 则更深入讲解评分。CapSkip 是一款 本地验证码识别工具,因此这里的每一次识别都在你自己的机器上完成。
