You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Rails中仅页面跳转时出现ReCAPTCHA BROWSER_ERROR问题

Rails Turbo跳转后Google ReCAPTCHA Enterprise出现BROWSER_ERROR的解决方案

问题场景

Rails应用集成Google ReCAPTCHA Enterprise后,直接刷新页面提交表单完全正常;但通过Turbo驱动的link_to跳转至表单页面时,后端调用create_assessment会返回token_properties.valid为false,且invalid_reason为:BROWSER_ERROR。

核心原因

Turbo采用局部页面更新机制,不会重新加载整个页面的JavaScript执行上下文。ReCAPTCHA Enterprise的初始化依赖页面首次加载时的全局环境绑定,Turbo跳转后,原有的grecaptcha实例状态失效,导致生成的token无法通过谷歌的验证逻辑。

解决方案

通过监听Turbo的turbo:load事件,在每次页面加载(包括Turbo跳转)时重置ReCAPTCHA状态,并确保表单提交事件正确绑定到新DOM元素:

1. 前端代码调整

修改ReCAPTCHA相关的JavaScript逻辑,添加Turbo事件监听和状态重置:

document.addEventListener('turbo:load', () => {
  // 绑定表单提交事件(事件委托适配Turbo动态渲染的表单)
  document.addEventListener('submit', async (event) => {
    const form = event.target;
    // 仅处理标记了ReCAPTCHA动作的表单(给表单添加data-recaptcha-action属性)
    if (form.hasAttribute('data-recaptcha-action') && !form.querySelector('[name=recaptcha]')) {
      event.preventDefault();
      const action = form.getAttribute('data-recaptcha-action');
      
      try {
        const recaptchaData = await recaptcha(action);
        const input = document.createElement('input');
        input.setAttribute('name', 'recaptcha');
        input.setAttribute('value', JSON.stringify(recaptchaData));
        input.classList.add('d-none');
        form.appendChild(input);
        form.querySelector('[type=submit]').click();
      } catch (error) {
        console.error('ReCAPTCHA token获取失败:', error);
        // 可在此添加用户可见的错误提示
      }
    }
  });

  // 重置或重新初始化ReCAPTCHA Enterprise
  if (typeof grecaptcha !== 'undefined' && grecaptcha.enterprise) {
    // 重置现有实例状态,适配Turbo跳转后的环境
    grecaptcha.enterprise.reset();
  } else {
    // 若ReCAPTCHA脚本未加载,动态注入脚本
    const siteKeyElement = document.getElementById('recaptcha-site-key');
    if (siteKeyElement) {
      const siteKey = siteKeyElement.textContent;
      const script = document.createElement('script');
      script.src = `https://www.google.com/recaptcha/enterprise.js?render=${siteKey}`;
      script.async = true;
      script.defer = true;
      document.body.appendChild(script);
    }
  }
});

export function recaptcha(action) {
  return new Promise((resolve, reject) => {
    // 确保grecaptcha ready后再执行
    grecaptcha.enterprise.ready(async () => {
      try {
        const token = await grecaptcha.enterprise.execute(
          document.getElementById('recaptcha-site-key').textContent, 
          { action }
        );
        resolve({ token, action });
      } catch (error) {
        reject(error);
      }
    });
  });
}

2. 表单标记调整

在需要ReCAPTCHA的表单上添加data-recaptcha-action属性,指定对应的动作名称:

<%= form_with(model: @model, html: { 'data-recaptcha-action': 'submit_form' }) do |form| %>
  <!-- 表单内容 -->
  <%= form.submit '提交' %>
<% end %>

3. 后端代码确认

你的后端创建评估的代码无需修改,但需确保:

  • site_key和project_id配置正确,与谷歌控制台一致
  • 从前端接收的recaptcha参数正确解析为token和action

验证步骤

  1. 通过Turbo链接跳转到表单页面
  2. 提交表单,检查后端是否能成功创建评估,无:BROWSER_ERROR
  3. 多次跳转后重复验证,确保状态稳定

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 00:53:32