我处于困境中,而Javascript世界--这是非常奇怪的。
在继续表单提交之前,我需要使用reCAPTCHA v3令牌解析创建一个表单。由于某些事件被绑定到表单submit
事件,所以事件循环必须等待直到它被解析,否则它会失败:
一些表单具有验证事件,如果存在错误(例如输入中的无效值),则
。
当我试图为submit
事件设置一个侦听器时,会阻止提交,直到令牌被解析为止,才会继续处理其他侦听器。
目前,reCAPTCHA脚本上的文档为零,而且我还没有找到一种实际有效地解析令牌的可靠方法。reCAPTCHA脚本是异步的,因此无法等到令牌被解析后才能使用。
// 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.
});
发布于 2020-05-26 16:21:36
知道了,没有办法使recaptcha.execute()
同步。换句话说,等待服务器解析令牌是不可能的。
相反,您应该通过请求一个初始令牌,然后在100秒的间隔内设置相同的操作,以确保令牌在到期前被接收到,从而不加注意地敲击reCAPTCHA服务器。
此代码针对许多表单进行了调整。使用风险自负。
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);
});
发布于 2021-01-26 10:22:10
我也有过同样的问题。这是我的解决办法:
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应答。我希望这会有所帮助。
发布于 2020-05-26 08:33:41
您只需禁用表单提交,直到加载令牌,然后显示一些加载程序。在then
回调中,将令牌保存在表单字段中,并启用表单提交(并隐藏加载程序)。
如果希望使其更加无缝,可以向用户隐藏此过程:如果用户在加载令牌之前提交表单,则禁用按钮(并防止常规提交尝试)并显示加载程序,并记住提交是挂起的;当稍后收到令牌时,您可以检查提交是否挂起,如果是,则以编程方式提交表单(包括令牌)。
这样,除非用户提交表单太早,否则不会遇到加载程序。
https://stackoverflow.com/questions/62015796
复制相似问题