ExpressionEngine 1.7.1站点Recaptcha Enterprise后端验证配置求助
我是reCAPTCHA配置新手,我的ExpressionEngine 1.7.1站点的联系表单一直被机器人垃圾邮件骚扰。已经在前端部署了reCAPTCHA Enterprise(复选框和提交按钮能正常工作),但完全搞不懂后端验证该怎么操作。
按照官方验证步骤第2步要求:
- 创建request.json请求体文件,替换内容:
- TOKEN:grecaptcha.enterprise.execute()返回的令牌;
- USER_ACTION:可选,grecaptcha.enterprise.execute()里指定的用户操作。
示例代码:
{ "event": { "token": "TOKEN", "expectedAction": "USER_ACTION", "siteKey": "6LeMq2cqAAAAAPBeXXbtOmywRCm19nqtiVNjsM4f", } } - 把JSON数据通过HTTP POST请求发送到指定URL,替换API_KEY为项目关联的API密钥:
https://recaptchaenterprise.googleapis.com/v1/projects/my-project-5516-1729255665478/assessments?key=API_KEY
我已经创建了request.json并上传到服务器,内容如下:
{ "event": { "token": "SUBMIT", "expectedAction": "USER_ACTION", "siteKey": "6LeMq2cqAAAAAK0KBDOjvRmBDkTTZIlw-XqtGrfL", } }
但我完全不知道怎么「发送HTTP POST请求」,试着用Postman调用普通reCAPTCHA验证接口https://www.google.com/recaptcha/api/siteverify?secret="put in my secret key"&response=,返回了错误:
{ "success": false, "error-codes": [ "invalid-input-response" ] }
请求状态是200 OK,但垃圾邮件还是不断进来,说明后端配置有问题。
另外,我在服务器根目录找到了一个vendor_autoload.php文件,代码如下,麻烦指导我怎么用这个文件完成后端验证:
<?php require 'vendor/autoload.php'; // Include Google Cloud dependencies using Composer use Google\Cloud\RecaptchaEnterprise\V1\RecaptchaEnterpriseServiceClient; use Google\Cloud\RecaptchaEnterprise\V1\Event; use Google\Cloud\RecaptchaEnterprise\V1\Assessment; use Google\Cloud\RecaptchaEnterprise\V1\TokenProperties\InvalidReason; /** * Create an assessment to analyze the risk of a UI action. * @param string $recaptchaKey The reCAPTCHA key associated with the site/app * @param string $token The generated token obtained from the client. * @param string $project Your Google Cloud Project ID. * @param string $action Action name corresponding to the token. */ function create_assessment( string $recaptchaKey, string $token, string $project, string $action ): void { // Create the reCAPTCHA client. // TODO: Cache the client generation code (recommended) or call client.close() before exiting the method. $client = new RecaptchaEnterpriseServiceClient(); $projectName = $client->projectName($project); // Set the properties of the event to be tracked. $event = (new Event()) ->setSiteKey($recaptchaKey) ->setToken($token); // Build the assessment request. $assessment = (new Assessment()) ->setEvent($event); try { $response = $client->createAssessment( $projectName, $assessment ); // Check if the token is valid. if ($response->getTokenProperties()->getValid() == false) { printf('The CreateAssessment() call failed because the token was invalid for the following reason: '); printf(InvalidReason::name($response->getTokenProperties()->getInvalidReason())); return; } // Check if the expected action was executed. if ($response->getTokenProperties()->getAction() == $action) { // Get the risk score and the reason(s). // For more information on interpreting the assessment, see: // https://cloud.google.com/recaptcha-enterprise/docs/interpret-assessment printf('The score for the protection action is:'); printf($response->getRiskAnalysis()->getScore()); } else { printf('The action attribute in your reCAPTCHA tag does not match the action you are expecting to score'); } } catch (exception $e) { printf('CreateAssessment() call failed with the following error: '); printf($e); } } // TODO: Replace the token and reCAPTCHA action variables before running the sample. create_assessment( '6LeMq2cqAAAAAPBeXXbtOmywRCm19nqtiVNjsM4f', 'YOUR_USER_RESPONSE_TOKEN', 'my-project-5516-1729255665478', 'YOUR_RECAPTCHA_ACTION' ); ?>
后端验证实现步骤(基于现有PHP文件)
1. 修正request.json的错误
你的request.json里把token设成了"SUBMIT",这是错误的——这个值必须是前端grecaptcha.enterprise.execute()调用返回的动态令牌,不是固定字符串。你不需要单独维护这个文件,直接用PHP处理前端提交的令牌即可。
2. 修改现有PHP文件,对接表单提交流程
把vendor_autoload.php改成一个验证接口,接收前端POST过来的令牌和动作参数:
<?php require 'vendor/autoload.php'; use Google\Cloud\RecaptchaEnterprise\V1\RecaptchaEnterpriseServiceClient; use Google\Cloud\RecaptchaEnterprise\V1\Event; use Google\Cloud\RecaptchaEnterprise\V1\Assessment; use Google\Cloud\RecaptchaEnterprise\V1\TokenProperties\InvalidReason; // 从前端POST请求获取令牌和动作 $token = $_POST['recaptcha_token'] ?? ''; $action = $_POST['recaptcha_action'] ?? 'submit_form'; // 要和前端execute里的action一致 $recaptchaKey = '6LeMq2cqAAAAAK0KBDOjvRmBDkTTZIlw-XqtGrfL'; // 你的siteKey $projectId = 'my-project-5516-1729255665478'; // 你的GCP项目ID function verify_recaptcha($recaptchaKey, $token, $projectId, $action) { $client = new RecaptchaEnterpriseServiceClient(); $projectName = $client->projectName($projectId); $event = (new Event()) ->setSiteKey($recaptchaKey) ->setToken($token); $assessment = (new Assessment()) ->setEvent($event); try { $response = $client->createAssessment($projectName, $assessment); // 验证令牌有效性 if (!$response->getTokenProperties()->getValid()) { $reason = InvalidReason::name($response->getTokenProperties()->getInvalidReason()); return ['success' => false, 'error' => "令牌无效:{$reason}"]; } // 验证动作一致性 if ($response->getTokenProperties()->getAction() !== $action) { return ['success' => false, 'error' => '动作不匹配']; } // 获取风险分数(通常分数>=0.5视为正常用户) $score = $response->getRiskAnalysis()->getScore(); return ['success' => true, 'score' => $score]; } catch (Exception $e) { return ['success' => false, 'error' => "验证失败:{$e->getMessage()}"]; } } // 执行验证并返回结果 $result = verify_recaptcha($recaptchaKey, $token, $projectId, $action); // 如果你是在ExpressionEngine的表单处理脚本里调用,直接用$result判断 if ($result['success'] && $result['score'] >= 0.5) { // 验证通过,继续处理表单提交(发送邮件等) } else { // 验证失败,拒绝提交,提示错误 die(json_encode($result)); } ?>
3. 前端修改:提交表单时传递令牌
确保前端调用grecaptcha.enterprise.execute()获取令牌,然后把令牌和动作一起提交到后端:
// 假设你的表单ID是contact-form document.getElementById('contact-form').addEventListener('submit', function(e) { e.preventDefault(); const siteKey = '6LeMq2cqAAAAAK0KBDOjvRmBDkTTZIlw-XqtGrfL'; const action = 'submit_form'; // 和后端的action参数一致 grecaptcha.enterprise.execute(siteKey, {action: action}).then(function(token) { // 把令牌添加到表单数据里 const formData = new FormData(this); formData.append('recaptcha_token', token); formData.append('recaptcha_action', action); // 提交表单 fetch('你的表单处理脚本路径.php', { method: 'POST', body: formData }).then(response => response.json()) .then(data => { if (data.success) { // 提交成功提示 } else { // 显示错误信息 alert(data.error); } }); }); });
4. 不要混用普通reCAPTCHA接口
你之前调用的https://www.google.com/recaptcha/api/siteverify是普通reCAPTCHA的验证接口,和reCAPTCHA Enterprise不兼容,所以会返回错误。必须用Enterprise的验证方式(也就是上面的PHP客户端或者官方的POST接口)。
内容的提问来源于stack exchange,提问作者phfeiler

