如何验证Google reCAPTCHA V3响应?PHP前后端集成故障排查
解决Google reCAPTCHA V3与PHP后端的集成验证问题
你的代码核心问题是前端没有将reCAPTCHA生成的响应值传递给后端,而且当前的执行逻辑也不够严谨,导致后端无法接收到验证所需的参数。下面是完整的修复方案,我会一步步拆解说明:
一、修正前端代码
reCAPTCHA V3是无交互的隐形验证,需要把验证得到的响应值存入隐藏表单字段,随表单一起提交给后端。同时建议在表单提交时触发验证,避免响应值过期:
<html> <head> <!-- 加载reCAPTCHA脚本,替换成你的site key --> <script src='https://www.google.com/recaptcha/api.js?render=你的Site_Key'></script> </head> <body> <form id="contactForm" action="verify.php" method="post"> <input type="text" name="name" placeholder="Your name" required> <input type="email" name="email" placeholder="Your email address" required> <textarea name="message" placeholder="Type your message here...." required></textarea> <!-- 添加隐藏字段存储reCAPTCHA响应值 --> <input type="hidden" name="g-recaptcha-response" id="g-recaptcha-response"> <input type="submit" name="submit" value="SUBMIT"> </form> <script> // 表单提交时触发reCAPTCHA验证 document.getElementById("contactForm").addEventListener("submit", function(e) { e.preventDefault(); // 先阻止表单默认提交 grecaptcha.ready(function() { // 执行验证,替换成你的site key和action名称(要和后端一致) grecaptcha.execute('你的Site_Key', { action: 'contact_submit' }).then(function(token) { // 将响应值存入隐藏字段 document.getElementById('g-recaptcha-response').value = token; // 提交表单 document.getElementById("contactForm").submit(); }); }); }); </script> </body> </html>
前端关键调整点:
- 添加了
id="g-recaptcha-response"的隐藏input,用于存储验证token - 监听表单提交事件,先执行reCAPTCHA验证,拿到token后再提交表单
- 确保
action参数前后端保持一致(这里用了contact_submit,你可以自定义但要统一)
二、修正后端Verify.php代码
后端需要接收前端传递的token,调用Google的验证接口,同时还要验证action匹配度、设置分数阈值(V3会返回0-1的分数,建议设置≥0.5的阈值拦截机器人)。另外,file_get_contents可能在部分服务器环境被禁用,用cURL更可靠:
<?php // 检查是否收到reCAPTCHA响应值 if(isset($_POST['g-recaptcha-response']) && !empty($_POST['g-recaptcha-response'])) { // 替换成你的Secret Key $secretKey = "你的Secret_Key"; $captchaResponse = $_POST['g-recaptcha-response']; $userIp = $_SERVER['REMOTE_ADDR']; // 获取用户IP,可选但建议传递 // 构建验证请求参数 $params = [ 'secret' => $secretKey, 'response' => $captchaResponse, 'remoteip' => $userIp ]; // 用cURL发送请求(比file_get_contents更稳定) $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, "https://www.google.com/recaptcha/api/siteverify"); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($params)); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); $verifyResponse = curl_exec($ch); curl_close($ch); $responseData = json_decode($verifyResponse); // 验证核心条件:成功、action匹配、分数达标 if($responseData->success && $responseData->action === 'contact_submit' && $responseData->score >= 0.5) { echo "验证通过!表单可以正常处理"; // 这里写你的表单逻辑,比如发送邮件、存储数据等 } else { // 输出具体错误信息方便调试 $errors = isset($responseData->{'error-codes'}) ? implode(', ', $responseData->{'error-codes'}) : '未知错误'; echo "验证失败:" . $errors . ",分数:" . $responseData->score; } } else { echo "未收到reCAPTCHA验证响应,请检查前端代码"; } ?>
后端关键调整点:
- 使用cURL替代
file_get_contents,提升兼容性和稳定性 - 增加了
action匹配验证,确保请求来自预期的操作 - 增加了分数阈值判断(≥0.5),过滤低可信度的请求
- 输出具体错误码,方便调试问题
三、注意事项
- 替换密钥:一定要把代码中的
你的Site_Key和你的Secret_Key替换成Google reCAPTCHA控制台获取的真实密钥 - Action一致性:前后端的
action参数必须完全一致,否则验证会失败 - 分数阈值:根据你的业务场景调整分数阈值,比如登录、支付等敏感操作可以设置≥0.7
- 调试技巧:如果验证失败,可以打印
$responseData查看具体错误码,方便定位问题
内容的提问来源于stack exchange,提问作者Karthik
相关产品推荐
相关产品推荐

