在Google recaptcha关闭挑战窗口时检测

问题描述 投票:10回答:2

我正在使用Google隐形recaptcha。有没有办法检测挑战窗口什么时候关闭?通过挑战窗口,我指的是您必须选择一些图像进行验证的窗口。

一旦按下按钮,我现在在按钮上放置一个微调器,该按钮呈现recaptcha挑战。无法通过另一个挑战窗口提示用户。

我以编程方式调用render函数:

grecaptcha.render(htmlElement, { callback: this.verified, expiredCallback: this.resetRecaptcha, sitekey: this.siteKey, theme: "light", size: "invisible" });

我有2个回调函数连接验证和resetRecaptcha函数,如下所示:

function resetRecaptcha() {
        grecaptcha.reset();
    }

function verified(recaptchaResponse)
{
/*
which calls the server to validate
*/
}

我原以为grecaptcha.render有另一个回调,当挑战屏幕关闭而没有用户通过选择图像验证自己时调用。

javascript callback recaptcha invisible-recaptcha
2个回答
13
投票

如您所述,API不支持此功能。

但是,您可以自己添加此功能。您可以谨慎使用以下代码,Google可能会更改其reCaptcha,并通过这样做来破坏此自定义代码。该解决方案依赖于reCaptcha的两个特性,因此如果代码不起作用,请先查看:

  • 窗口iframe src:包含“google.com/recaptcha/api2/bframe”
  • CSS opacity属性:窗口关闭时更改为0

// to begin: we listen to the click on our submit button
// where the invisible reCaptcha has been attachtted to
// when clicked the first time, we setup the close listener
recaptchaButton.addEventListener('click', function(){
    if(!window.recaptchaCloseListener) initListener()

})

function initListener() {

    // set a global to tell that we are listening
    window.recaptchaCloseListener = true

    // find the open reCaptcha window
    HTMLCollection.prototype.find = Array.prototype.find
    var recaptchaWindow = document
        .getElementsByTagName('iframe')
        .find(x=>x.src.includes('google.com/recaptcha/api2/bframe'))
        .parentNode.parentNode

    // and now we are listening on CSS changes on it
    // when the opacity has been changed to 0 we know that
    // the window has been closed
    new MutationObserver(x => recaptchaWindow.style.opacity == 0 && onClose())
        .observe(recaptchaWindow, { attributes: true, attributeFilter: ['style'] })

}

// now do something with this information
function onClose() {
    console.log('recaptcha window has been closed')
}

1
投票

要在IE中工作,此解决方案需要.include()和Array.from()的polyfill,如下所示:

Array.from on the Internet Explorer

ie does not support 'includes' method

更新的代码:

function initListener(){

              // set a global to tell that we are listening
              window.recaptchaCloseListener = true

              // find the open reCaptcha window

                    var frames = Array.from(document.getElementsByTagName('iframe'));
                    var recaptchaWindow;

                    frames.forEach(function(x){

                        if (x.src.includes('google.com/recaptcha/api2/bframe') ){
                            recaptchaWindow = x.parentNode.parentNode;
                        };

                    });

              // and now we are listening on CSS changes on it
              // when the opacity has been changed to 0 we know that
                // the window has been closed

                new MutationObserver(function(){
                    recaptchaWindow.style.opacity == 0 && onClose();
                })
                  .observe(recaptchaWindow, { attributes: true, attributeFilter: ['style'] })

            }

0
投票

我的解决方案

let removeRecaptchaOverlayEventListener = null
const reassignGRecatchaExecute = () => {
  if (!window.grecaptcha || !window.grecaptcha.execute) {
    return
  }
  /* save original grecaptcha.execute */
  const originalExecute = window.grecaptcha.execute
  window.grecaptcha.execute = (...params) => {
    try {
      /* find challenge iframe */
      const recaptchaIframe = [...document.body.getElementsByTagName('iframe')].find(el => el.src.match('https://www.google.com/recaptcha/api2/bframe'))
      const recaptchaOverlay = recaptchaIframe.parentElement.parentElement.firstElementChild
      /* detect when the recaptcha challenge window is closed and reset captcha */
      !removeRecaptchaOverlayEventListener && recaptchaOverlay.addEventListener('click', window.grecaptcha.reset)
      /* save remove event listener for click event */
      removeRecaptchaOverlayEventListener = () => recaptchaOverlay.removeEventListener('click', window.grecaptcha.reset)
    } catch (error) {
      console.error(error)
    } finally {
      originalExecute(...params)
    }
  }
}

运行window.grecaptcha.render()之后和window.grecaptcha.execute()之前调用此函数

并且不要忘记删除事件监听器:removeRecaptchaOverlayEventListener()

© www.soinside.com 2019 - 2024. All rights reserved.