首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >如何同步等待reCAPTCHA v3令牌?

如何同步等待reCAPTCHA v3令牌?
EN

Stack Overflow用户
提问于 2020-05-26 06:17:08
回答 4查看 4.4K关注 0票数 1

我处于困境中,而Javascript世界--这是非常奇怪的。

在继续表单提交之前,我需要使用reCAPTCHA v3令牌解析创建一个表单。由于某些事件被绑定到表单submit事件,所以事件循环必须等待直到它被解析,否则它会失败:

一些表单具有验证事件,如果存在错误(例如输入中的无效值),则

  • 会阻止提交。如果用户在页面加载时单击表单过快(由于自动完成),并且仍然没有检索令牌,则请求返回错误。

当我试图为submit事件设置一个侦听器时,会阻止提交,直到令牌被解析为止,才会继续处理其他侦听器。

目前,reCAPTCHA脚本上的文档为零,而且我还没有找到一种实际有效地解析令牌的可靠方法。reCAPTCHA脚本是异步的,因此无法等到令牌被解析后才能使用。

代码语言:javascript
代码运行次数:0
运行
复制
// Let's retrieve the form by its id.
let form = document.getElementById('example_form');

let addToken = (form) => {
    grecaptcha.execute('site_key', {
        // some options
    }).then(token => {
        // Include the token as an input inside the form so it's sent.
    });
};

form.addEventListener('submit', () => {
    return addToken(form); // <-- This won't work, since it's async.
});
EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2020-05-27 00:21:36

知道了,没有办法使recaptcha.execute()同步。换句话说,等待服务器解析令牌是不可能的。

相反,您应该通过请求一个初始令牌,然后在100秒的间隔内设置相同的操作,以确保令牌在到期前被接收到,从而不加注意地敲击reCAPTCHA服务器。

此代码针对许多表单进行了调整。使用风险自负。

代码语言:javascript
代码运行次数:0
运行
复制
const site_key = 'HEREYOURSITEKEY';

// This function retrieves the token from reCAPTCHA.
const retrieveToken = (form) => {
    // Mark the form as unresolved until the retrieval ends.
    form.unresolved = true;
    // Get the token.
    grecaptcha.execute(site_key, {
        action: form.action.substring(action.indexOf('?'), action.length).replace(/[^A-z\/_]/gi, '')
    }).then(token => {
        // Append the token to the form so it's sent along the other data.
        let child = document.createElement('input');
        child.setAttribute('type', 'hidden');
        child.setAttribute('name', '_recaptcha');
        child.setAttribute('value', token);
        form.appendChild(child);
        form.unresolved = false;
    });
};

// We will loop for each form in the document. You can add a "filter" method if you want.
Array.from(document.getElementByTagName('form'))
    .forEach(form => {
        // Mark it as unresolved from the beginning.
        form.unresolved = true;
        // Add an event listener that disables submission if the form is unresolved.
        form.addEventListener('submit', event => {
            if (form.unresolved) {
                event.preventDefault();
            }
        });
        // Resolve the token at startup.
        retrieveToken(form);
        // And retrieve a new token each 100 seconds. Bite me.
        setInterval(() => refreshToken(form), 100 * 1000);
    });
票数 1
EN

Stack Overflow用户

发布于 2021-01-26 18:22:10

我也有过同样的问题。这是我的解决办法:

代码语言:javascript
代码运行次数:0
运行
复制
async function recaptchaCall(){
  var recaptcha_token = '';
  grecaptcha.ready(() => {
    grecaptcha.execute(grecaptchaKey, {action: 'submit'}).then((token) => {
      recaptcha_token = token;
    });
  });
  while(recaptcha_token == ''){
    await new Promise(r => setTimeout(r, 100));
  }
  return recaptcha_token; 
}

let recaptcha_token = await recaptchaCall();

我认为这是最好的解决方案,因为它不可能使它作为一个同步的功能正确。我使用setTimeout等待直到收到Recaptcha应答。我希望这会有所帮助。

票数 2
EN

Stack Overflow用户

发布于 2020-05-26 16:33:41

您只需禁用表单提交,直到加载令牌,然后显示一些加载程序。在then回调中,将令牌保存在表单字段中,并启用表单提交(并隐藏加载程序)。

如果希望使其更加无缝,可以向用户隐藏此过程:如果用户在加载令牌之前提交表单,则禁用按钮(并防止常规提交尝试)并显示加载程序,并记住提交是挂起的;当稍后收到令牌时,您可以检查提交是否挂起,如果是,则以编程方式提交表单(包括令牌)。

这样,除非用户提交表单太早,否则不会遇到加载程序。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/62015796

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档