You need to enable JavaScript to run this app. 排查Invisible reCaptcha失效、表单可直接提交的问题与测试方法
优惠活动
大模型
产品
解决方案
定价
更多

排查Invisible reCaptcha失效、表单可直接提交的问题与测试方法

代码问题定位

前端逻辑的可利用漏洞

  • 你在reCaptcha回调里直接调用form.submit()时,这个原生方法会完全绕过你绑定的所有submit事件监听器。攻击者只需要在DevTools里直接调用这个原生提交方法,根本不会触发你写的“检查是否有captcha响应”的判断逻辑,这就是为什么你用模拟Googlebot的方式能成功提交、还收到几十封垃圾邮件的核心原因。
  • 哪怕是正常流程下,reCaptcha校验通过后走的原生form.submit()也没有把验证响应值传递到服务端,服务端根本拿不到验证结果,等于完全没起到校验作用。

缺失核心的服务端校验

所有前端的JS校验都可以被轻松绕过:bot不需要加载你的页面JS,直接向scripts/mail.php发POST请求就能提交数据。你现在的代码完全没有在服务端对接reCaptcha的校验环节,整个防护是完全暴露的,就算前端逻辑写得再严谨,也挡不住直接打接口的bot。

细节隐患

  • 你用async defer加载reCaptcha脚本时,存在加载时序问题:如果用户在组件加载完成前点击提交,直接调用grecaptcha.getResponse()会抛出未定义的JS错误,因为错误发生在事件回调里,很容易被忽略,导致提交逻辑直接中断。
  • 全局挂载的onCompleted函数没有做作用域隔离,很容易被页面其他脚本覆盖,导致reCaptcha的回调根本不触发。
可直接落地的修正方案

前端代码调整

<head>
  <!-- 替换为你自己的站点key,指定render参数实现显式初始化 -->
  <script src="https://www.google.com/recaptcha/api.js?render=你的站点key" async defer></script>
</head>
<body>
  <form method="post" action="scripts/mail.php" id="contact-form">
    <input type="text" name="input" placeholder="Some input fields">
    <button type="submit">Send</button>
  </form>

  <script>
    const contactForm = document.getElementById('contact-form');

    // 统一的最终提交逻辑,避免重复写校验
    const submitForm = () => {
      // 提交前二次校验captcha响应
      const captchaToken = grecaptcha.getResponse();
      if (!captchaToken) return;

      // 把captcha token挂载到表单,随请求发给服务端
      const hiddenToken = document.createElement('input');
      hiddenToken.type = 'hidden';
      hiddenToken.name = 'g-recaptcha-response';
      hiddenToken.value = captchaToken;
      contactForm.appendChild(hiddenToken);

      // 正式提交
      contactForm.submit();
    }

    contactForm.addEventListener('submit', (e) => {
      e.preventDefault();
      // 先处理组件未加载完成的异常
      if (typeof grecaptcha === 'undefined') {
        alert('安全验证组件加载中,请稍后重试');
        return;
      }
      // 已有有效验证的情况直接提交
      if (grecaptcha.getResponse()) {
        submitForm();
        return;
      }
      // 触发invisible reCaptcha校验,通过后执行提交
      grecaptcha.ready(() => {
        grecaptcha.execute('你的站点key', {action: 'contact_submit'}).then(() => {
          submitForm();
        })
      })
    })
  </script>
</body>

服务端强制校验要求

  • 前端把g-recaptcha-response字段传给服务端后,服务端必须使用自己的reCaptcha密钥,校验该token的合法性、来源站点是否匹配、风险评分是否达到你设置的阈值。
  • 只有服务端校验完全通过的请求,才能执行后续发邮件的逻辑,这是拦截bot的核心防线,没有这个环节所有前端防护都形同虚设。
reCaptcha生效性的验证方法
  • 前端拦截验证:打开DevTools控制台,手动执行document.getElementById('contact-form').submit(),正常情况下该调用会被绑定的submit事件拦截,不会直接发出请求。
  • 接口防护验证:用接口工具直接向scripts/mail.php发送不带g-recaptcha-response字段的POST请求,正常情况下服务端会直接拒绝执行发信操作,返回错误提示,不会真正发送邮件。
  • 后台数据验证:登录reCaptcha管理后台,看对应站点的请求统计,正常真人提交的请求会有对应动作标识,风险评分大多在0.7以上,bot请求的评分会低于0.3,且不会带上合法的action标识。

内容的提问来源于stack exchange,提问作者KimMai

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.11.10 20:54:02