ruby-on-rails ReCAPTCHA BROWSER_ERROR仅在导航到Rails中的另一个页面时发生

2ic8powd  于 7个月前  发布在  Ruby
关注(0)|答案(1)|浏览(84)

我有一个使用Google ReCAPTCHA Enterprise的Rails应用程序。我已经根据他们的文档完成了所有设置,当我在提交表单之前立即刷新页面时,它都能正常工作。但是,如果我使用link_to或其他一些turbo链接从另一个页面导航到该页面,那么当我尝试创建评估时,以下情况是正确的:!response.token_properties.valid && response.token_properties.invalid_reason == :BROWSER_ERROR
我的假设是,当你第一次加载recaptcha时,它会做一些特殊的事情,一旦你导航到另一个页面,它就会被否定或撤销。然而,我似乎在文档中找不到任何关于这个问题的信息,也没有其他人抱怨这个问题。
下面的代码描述了我首先是如何获得令牌的:

const form = this
        if (!form.querySelector('[name=recaptcha]')) {
            event.preventDefault()
            const input = document.createElement('input');
            input.setAttribute('name', 'recaptcha');
            input.setAttribute('value', JSON.stringify(await recaptcha(action)));
            input.classList.add('d-none')
            form.appendChild(input);
            form.querySelector('[type=submit]').click()
        }

...

export function recaptcha(action) {
  return new Promise((resolve, reject) => {
    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);
      }
    });
  });
}

字符串
下面介绍了我如何创建评估:

client = ::Google::Cloud::RecaptchaEnterprise.recaptcha_enterprise_service do |config|
      credentials = SecretGetter.call(:recaptcha_credentials)
      config.credentials = JSON.parse(credentials)
    end

    request = {
      parent: "projects/#{Rails.application.config.x.recaptcha.project_id}",
      assessment: {
        event: {
          site_key: Rails.application.config.x.recaptcha.site_key,
          token: @token
        }
      }
    }

    response = client.create_assessment request


我不怀疑我创建评估的方式是问题所在,因为,只要我先刷新页面,它就能工作。解决这个问题的最好方法可能是确定一些我需要在turbo:load上调用的recaptcha函数,它将刷新recaptcha并准备好响应。

a7qyws3x

a7qyws3x1#

我可以通过将脚本挂接到我的一个recaptcha控制器的connect方法来手动加载turbo load,这使得它即使在点击turbo链接后也能工作。

function loadScript(url) {
    return new Promise((resolve, reject) => {
        let script = document.createElement('script');
        script.src = url;
        script.async = true;
        script.onload = resolve;
        script.onerror = reject;
        document.head.appendChild(script);
    });
}

export default class extends Controller {
    async connect() {
        await loadScript(`https://www.google.com/recaptcha/enterprise.js?render=${this.element.dataset.recaptchaSiteKey}`)
    }

    async submit(event) {
        event.preventDefault()
        const action = event.target.dataset.recaptchaAction
        const recaptcha = JSON.stringify(await this.recaptcha(action))
        event.detail.fetchOptions.body.append('recaptcha', recaptcha)
        event.detail.resume()
    }

    recaptcha(action) {
        return new Promise((resolve, reject) => {
            grecaptcha.enterprise.ready(async () => {
                try {
                    const token = await grecaptcha.enterprise.execute(
                        this.element.dataset.recaptchaSiteKey, {action}
                    );
                    resolve({token, action})
                } catch (error) {
                    console.log('error', error)
                    reject(error)
                }
            })
        })
    }
}

字符串

相关问题