如何用 Node.js 识别 reCAPTCHA v3 并设置 action

reCAPTCHA v3 从不显示拼图。它会在后台悄悄为访问评分,并将一个 token 交给页面,网站在其自己的后端进行验证。对你而言没有任何需要点击的东西,因此整个任务就是生成一个网站会接受的 token。在 Node.js 中,这与用于 v2 的 recaptcha 方法相同,只是多了一个选项。
决定它能否成功的关键细节就是 action。
设置
npm install capskip
const { CapSkip } = require('capskip');
const solver = new CapSkip({
host: '127.0.0.1',
port: 8080,
recaptchaTimeout: 300, // seconds, shared with Turnstile and GeeTest
});CapSkip 在本地运行,因此在任何调用成功之前,必须先打开桌面应用。
基本调用
const result = await solver.recaptcha(
'6Lc...YOUR_SITEKEY',
'https://example.com/checkout',
{ version: 'v3', action: 'submit' },
);
console.log(result.code); // the v3 token与 v2 有两点不同: version: 'v3' 是必需的,而 action 应与页面传给 grecaptcha.execute的值一致。若不填写,则默认为 verify.
为什么 action 很重要
action 是网站为每个受保护的交互附加的标签,这样登录和结账就能被分别评分。大多数后端会检查 token 上的 action 是否与该端点所预期的一致。
如果发送了错误的标签,token 虽然真实,但会被标记为另一个交互,许多验证程序会因此拒绝它。请从页面读取真实值,而不要猜测:
const html = await (await fetch('https://example.com/checkout')).text();
// Sites normally call execute() with the action as a string literal.
const match = html.match(/execute\([^,]+,\s*\{\s*action:\s*['"]([^'"]+)/);
const action = match ? match[1] : 'verify';
const result = await solver.recaptcha(sitekey, pageUrl, {
version: 'v3',
action,
});常见的值有 login, submit, homepage 和 checkout,但它们只是网站构建者随意选定的字符串。
Enterprise v3
const result = await solver.recaptcha(sitekey, pageUrl, {
version: 'v3',
enterprise: 1,
action: 'submit',
});Enterprise 是一个正交的标志,而不是另一款产品,因此它只是叠加使用。可通过页面加载的脚本来区分二者:Enterprise 加载的是 enterprise.js,而标准版加载的是 api.js。猜错只会导致识别失败,而不会返回错误的 token,因此验证起来成本很低。
提交 token
const response = await fetch('https://example.com/checkout', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
token: result.code,
orderId: '...',
}),
});与 v2 不同,v3 没有标准的表单小组件,因此其集成方式各不相同。有些使用隐藏的 g-recaptcha-response 字段,有些则以自定义键提交 JSON。在假定字段名之前,请先查看页面自身的 JavaScript 是如何处理的。
批量识别
const tokens = await Promise.all(
urls.map((url) =>
solver.recaptcha(sitekey, url, { version: 'v3', action: 'submit' })),
);
console.log(tokens.map((t) => t.code));AsyncCapSkip 在此包中也存在,但它只是 CapSkip的别名。每个方法本身都会返回一个 Promise,因此 Promise.all 就是 Node 中并发处理的全部。
错误
const { ApiException, NetworkException } = require('capskip');
try {
const result = await solver.recaptcha(sitekey, pageUrl, { version: 'v3' });
} catch (err) {
if (err instanceof NetworkException) {
// CapSkip is not running on the configured port
} else if (err instanceof ApiException) {
// the sitekey or pageurl was rejected
} else {
throw err;
}
}常见问题
我能在提交前看到分数吗?
不能。分数保留在 Google 手中,只有当网站所有者的后端验证 token 时才会向其披露。在客户端你只会收到一个 token,别无其他,因此无法事先查看或按分数进行筛选。
如果页面没有可见的 action 怎么办?
有些页面调用 execute 时不带 action,这种情况下默认值 verify 是正确的。如果上面的正则表达式没有找到任何内容,通常正是这个原因,而不是解析失败。
v3 token 能维持多久?
大约两分钟,一次性使用,与 v2 相同。请在需要它的请求之前立即识别,而不要预先建立 token 池。
小结
传入 version: 'v3',将 action 设置为页面实际执行的值,添加 enterprise: 1 (当页面加载它时) enterprise.js,并尽快提交,因为 token 大约两分钟后就会过期。
其他语言在 reCAPTCHA v3 识别工具 页面介绍,Enterprise 的具体内容在 Enterprise 识别工具 页面介绍,更广泛的 Node 接口在 Node.js 验证码识别 页面介绍。你可以在我们的 v3 演示上进行实验。CapSkip 采用 验证码识别工具 在你自己的机器上运行。
