Google invisible reCAPTCHA仅隐身模式可用 grecaptcha.execute不执行求助
解决方案
1. 修复reCAPTCHA执行时序问题
你当前给reCAPTCHA脚本加了async defer属性,普通模式下可能出现页面逻辑加载完成但reCAPTCHA对象未初始化的情况,导致grecaptcha.execute()调用失败:
修改HTML部分
给reCAPTCHA容器增加唯一ID,避免多实例冲突:
<div class="g-recaptcha" id="recaptchaWidget" data-sitekey="Site_key" data-callback="sendMail" data-size="invisible"> </div>
修改提交按钮点击逻辑
增加grecaptcha对象存在性判断:
$("#contact_form_submit").on("click", function () { var co_name = $("#cont_name").val(); var co_email = $("#cont_email").val(); var co_phone = $("#cont_phone").val(); var co_company = $("#cont_company").val(); var co_message = $("#cont_msg").val(); if ( co_name != "" && co_email != "" && co_phone != "" && co_company != "" && co_message != "" ) { // 校验reCAPTCHA是否加载完成 if (typeof grecaptcha !== 'undefined') { grecaptcha.execute(); } else { $("#contact_err").html("验证组件加载中,请稍后重试"); } } else { $("#loading").hide(); $("#contact_form_submit").show(); $("#contact_err").html("请填写所有必填字段"); } });
2. 前端提交携带reCAPTCHA校验凭证
你当前的sendMail函数没有传递reCAPTCHA验证后的响应凭证给后端,是可绕过的核心原因之一,修改sendMail函数的提交参数:
function sendMail() { var co_name = $("#cont_name").val(); var co_email = $("#cont_email").val(); var co_phone = $("#cont_phone").val(); var co_company = $("#cont_company").val(); var co_message = $("#cont_msg").val(); let data = { username: co_name, useremail: co_email, userphone: co_phone, usercompany: co_company, usermessage: co_message, // 新增reCAPTCHA响应字段 'g-recaptcha-response': grecaptcha.getResponse() }; $("#loading").show(); $("#contact_form_submit").hide(); $.ajax({ type: "POST", url: "contact_ajaxmail.php", data: data, success: function (contact) { $("#loading").hide(); $("#contact_form_submit").show(); // 提交完成后重置reCAPTCHA,支持二次提交 grecaptcha.reset(); // 原有逻辑不变 var i = contact.split("#"); if (i[0] == "1") { $("#cont_name").val(""); $("#cont_email").val(""); $("#cont_phone").val(""); $("#cont_company").val(""); $("#cont_msg").val(""); $("#contact_err").html(i[1]); $(".app_form_wrapper .apps_input").addClass("success"); setTimeout(function () { $(".app_form_wrapper .apps_input").removeClass("success"); $(".app_form_wrapper .apps_input").removeClass("error"); $("#cont_email").parent().removeClass("error"); }, 2500); } else { $("#cont_name").val(data.username); $("#cont_email").val(data.useremail); $("#cont_phone").val(data.userphone); $("#cont_company").val(data.usercompany); $("#cont_msg").val(data.usermessage); $("#contact_err").html(i[1]); $( ".app_form_wrapper .apps_input input, .app_form_wrapper .apps_input textarea" ).each(function () { if (!$(this).val()) { $(this).parent().addClass("error"); } else { if (i[0] == 3) { $("#cont_email").parent().addClass("error"); } else { $(this).parent().addClass("error"); } $(this).parent().removeClass("error"); } }); } }, }); }
3. 后端增加reCAPTCHA校验(必须修改,否则永远可以绕过)
前端校验都是可绕过的,必须在后端contact_ajaxmail.php中增加校验逻辑:
- 接收前端传递的
g-recaptcha-response参数 - 使用你申请reCAPTCHA时得到的密钥(Secret Key,不可暴露在前端代码中),将密钥+接收的token+用户IP发送到谷歌校验接口
- 只有接口返回的
success字段为true时,才执行发邮件逻辑,否则直接返回错误
4. 模式差异说明
隐身模式下无浏览器缓存、无用户行为标签,所以reCAPTCHA更容易弹出校验窗口;普通模式下谷歌如果判定你是可信用户,隐形reCAPTCHA会直接通过,不会弹出校验弹窗,属于正常现象,只要后端校验逻辑正常就不会被绕过。
内容的提问来源于stack exchange,提问作者user15958535
相关产品推荐
相关产品推荐

