如何用 PHP 识别 reCAPTCHA v3 并设置 action

reCAPTCHA v3 从不渲染挑战。它会悄悄为访问评分,并给页面一个 token,随后由网站后端进行验证。从代码角度看,这意味着没有任何需要点击的东西,因此整个任务就是生成一个网站会接受的 token。在 PHP 中,这与你用于 v2 的 recaptcha 方法相同,只是在选项数组中加了一个版本标志。
决定它能否成功的关键是 action。
设置
# PHP 8.0+, with the curl and json extensions. composer require capskip/capskip
use CapSkip\CapSkip;
$solver = new CapSkip([
'host' => '127.0.0.1',
'port' => 8080,
'recaptchaTimeout' => 300, // seconds, shared with Turnstile and GeeTest
]);CapSkip 在你自己的机器上运行,因此必须先打开桌面应用。
基本调用
$result = $solver->recaptcha(
'6Lc...YOUR_SITEKEY',
'https://example.com/checkout',
[
'version' => 'v3',
'action' => 'submit',
]
);
echo $result['code']; // the v3 token与 v2 有两点不同。 version 必须为 v3,以及 action 应与页面传给 grecaptcha.execute的值一致。若省略,则默认为 verify.
为什么 action 很重要
action 是网站为每个受保护交互附加的标签,这样登录和结账就能被分别评分。大多数后端会检查 token 携带的 action 是否与该端点所预期的一致。
如果发送了错误的标签,token 虽然真实,但会被标记为另一个交互,许多验证程序会直接拒绝。请从页面读取真实值,而不要猜测:
$html = file_get_contents('https://example.com/checkout');
// Sites normally call execute() with the action as a string literal.
preg_match('/execute\([^,]+,\s*\{\s*action:\s*[\'"]([^\'"]+)/', $html, $m);
$action = $m[1] ?? 'verify';
$result = $solver->recaptcha($sitekey, $pageUrl, [
'version' => 'v3',
'action' => $action,
]);常见的值有 login, submit, homepage 和 checkout,但它们只是网站构建者随意选定的字符串。
Enterprise v3
$result = $solver->recaptcha($sitekey, $pageUrl, [
'version' => 'v3',
'enterprise' => 1,
'action' => 'submit',
]);Enterprise 是一个正交的标志,而不是一款独立产品,因此它叠加在 v3 调用之上。可通过页面加载的脚本来区分:Enterprise 加载的是 enterprise.js,而标准版加载的是 api.js。猜错只会导致识别失败,而不会返回错误的 token,因此测试起来毫无代价。
提交 token
$ch = curl_init('https://example.com/checkout');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ['Content-Type: application/json'],
CURLOPT_POSTFIELDS => json_encode([
'token' => $result['code'],
'order_id' => '...',
]),
]);
$response = curl_exec($ch);
curl_close($ch);与 v2 不同,没有标准的表单小组件来约束其形式,因此 v3 的集成方式各不相同。有些使用隐藏的 g-recaptcha-response 输入框,有些则以自定义键提交 JSON。在假定字段名之前,请先查看页面自身的 JavaScript。
错误
use CapSkip\Exceptions\ApiException;
use CapSkip\Exceptions\NetworkException;
use CapSkip\Exceptions\TimeoutException;
try {
$result = $solver->recaptcha($sitekey, $pageUrl, ['version' => 'v3']);
} catch (NetworkException $e) {
// CapSkip is not running on the configured port
} catch (ApiException $e) {
// the sitekey or pageurl was rejected
} catch (TimeoutException $e) {
// exceeded recaptchaTimeout
}同样要注意其中的 CapSkip\Exceptions 命名空间。从 Python 或 Node 示例中照搬 import 语句,是这里致命错误的常见来源。
常见问题
我能在提交前查看分数吗?
不能。分数保存在 Google 手中,只有当网站所有者的后端验证 token 时才会向其披露。在客户端你只会收到一个 token,别无其他,因此事先没有任何可查看或筛选的内容。
我应该在 Web 请求内部进行识别吗?
最好不要。PHP 是同步的,一次识别可能耗时数秒,因此在页面渲染期间执行会在此期间占用一个工作进程。请将其移入队列任务或 CLI 工作进程。
如果页面从不设置 action 怎么办?
有些页面调用 execute 时不带 action,这种情况下默认值 verify 是正确的。如果你的正则表达式没有找到任何内容,通常正是这个原因,而不是解析错误。
小结
设置 version 设置为 v3,让 action 与页面执行的值匹配,添加 enterprise (当页面加载它时) enterprise.js,从以下模块导入异常: CapSkip\Exceptions,并尽快提交 token,因为它大约两分钟后就会过期。
其他语言在 reCAPTCHA v3 识别工具 页面介绍,Enterprise 的详情在 Enterprise 识别工具 页面介绍,更广泛的 PHP 接口在 PHP 验证码识别 页面介绍。你可以在我们的 v3 演示上进行实验。CapSkip 采用 验证码识别工具 ,它运行在你自己的硬件上。
