【问题标题】:reCAPTCHA V3: how to deal with expired token after idle?reCAPTCHA V3:空闲后如何处理过期令牌?
【发布时间】:2019-06-23 13:35:07
【问题描述】:

对于 Google reCAPTCHA V2,当令牌因空闲而过期时该怎么做是很清楚的:客户需要再次单击 reCaptcha 复选框。 对于 Google reCAPTCHA V3,情况有所不同,因为不清楚令牌何时因空闲而过期。

对于 reCAPTCHA V3,Google 建议:

https://developers.google.com/recaptcha/docs/v3

  1. 使用您的站点密钥加载 JavaScript api

  2. 在操作或页面加载时调用 grecaptcha.execute // 我们选择页面加载的时间,好吗?

  3. 将令牌发送到您的后端请求验证 //点击按钮时

好的。如果在页面加载后几分钟点击按钮,我们发送到后端的 V3 令牌已经过期。 在这种情况下处理的正确方法是什么?我们是否应该通过每分钟向 Google 发送调用来静默自动更新令牌? 这种情况下最好的方法是什么?我没有找到来自 Google 的任何建议。

【问题讨论】:

  • 然后我会在按钮点击时执行它
  • 你发现了吗?我在用例 3 中遇到了同样的问题。我在页面加载时收到了令牌,但在表单发送到 BE 时它已经过期。
  • @JoãoBelo 是的。令牌必须在页面加载之后生成。它应该在我们将其发送到后端之前立即生成。换句话说,我们单击按钮(来自我的示例),然后获取生成的令牌,然后将令牌发送到我的后端。

标签: javascript token recaptcha recaptcha-v3


【解决方案1】:

令牌必须在页面加载之后生成。它应该在我们将其发送到后端之前生成。换句话说,我们点击按钮(来自我的示例),然后获取生成的令牌,然后将令牌发送到后端。

这个解决方案很有意义并解决了我的问题。

【讨论】:

  • 解决方案并不完美。因为,当我们在发送之前请求令牌时。表单需要等待几秒钟才能接收令牌并与数据一起发送。
【解决方案2】:

由于 reCAPTCHA 令牌在两分钟后过期,这就是我的工作方式:

第 1 步:在页面加载时加载验证码(照常)

第 2 步:使用 SetInterval 函数每 90 秒重新加载一次令牌,以便在 2 分钟后过期之前刷新 reCAPTCHA 令牌。

// Onload
grecaptcha.ready(function () {
  grecaptcha.execute('YOUR_KEY_HERE', { action: 'request_call_back' }).then(function (e) {
    $('#YOUR_FIELD_NAME_ID').val(e);
  });
});

// Every 90 Seconds
setInterval(function () {
  grecaptcha.ready(function () {
    grecaptcha.execute('YOUR_KEY_HERE', { action: 'request_call_back' }).then(function (e) {
      $('#YOUR_FIELD_NAME_ID').val(e);
    });
  });
}, 90 * 1000);

【讨论】:

    【解决方案3】:

    我以 asp.net 形式工作,但此解决方案可适用于任何语言。过期令牌的问题很烦人。

    token在v3中有2分钟的有效时间,但是google不推荐留一个定时器每2分钟刷新一次token的做法。他们建议仅在需要时刷新令牌。

    我选择了 javascript 解决方案,强制客户端点击刷新令牌的按钮。

    需要注意的是,如果刷新recaptcha时执行了“recaptcha.ready”,就会抛出错误,所以我不得不将“ready”和“execute”分开,这样recaptcha被刷新而没有错误。

    <script type="text/javascript" >
        grecaptcha.ready(function () {
          captcha_execute();
        });
    
        function captcha_execute() {
          grecaptcha.execute('<%=System.Configuration.ConfigurationManager.AppSettings("recaptcha-public-key").ToString %>', { action: 'ingreso_usuario_ext' }).then(function (token) {
            document.getElementById("g-recaptcha-response").value = token;
          });
        }
    
        function los_dos(token_viejo) {
          captcha_execute()
          clase_boton(token_viejo);
        }
    
        async function clase_boton(token_viejo) {
          btn_act = document.getElementById("Btn_Refrescar");
          btn = document.getElementById("Btn_Ingresar");
          btn.setAttribute("class", "button_gris");
          btn_act.style.display = "none";
          btn.style.display = "initial";
          btn.disabled = true;
    
          //token_viejo = document.getElementById("g-recaptcha-response").value;
          strToken = token_viejo;
          varCant = 0;
    
          while (strToken == token_viejo && varCant < 30) {
            strToken = document.getElementById("g-recaptcha-response").value;
            await sleep(100);
            varCant++;
          }
    
          btn.setAttribute("class", "button_azul");
          btn.disabled = false;
    
          setTimeout(refrescar_token, 120000);
        }
    
        function sleep(ms) {
          return new Promise(resolve => setTimeout(resolve, ms));
        }
    
        function refrescar_token() {
          btn_ing = document.getElementById("Btn_Ingresar");
          btn_act = document.getElementById("Btn_Refrescar");
          btn_act.style.display = "initial";
          btn_ing.style.display = "none";
        }
      </script>
    

    在体内

    <body style="background-color: #dededc;" onload="clase_boton('');" >
    

    按钮

     <asp:Button ID="Btn_Ingresar" runat="server" Text="Ingresar" CssClass="button_gris" Enabled="false" />
     <input type="button" id="Btn_Refrescar" name="Btn_Refrescar" class="button_verde" value="Refrescar Token" title="Refrescar Token" onclick="los_dos(document.getElementById('g-recaptcha-response').value);" style="display: none;" />
              
    

    使用 javascript,我等待令牌被填充,当它被填充时,我启用登录按钮。如果该过程花费的时间太长(由于某些错误),我仍然启用它。这是一个选择问题。

    2 分钟后(“setTimeout”),登录按钮变得不可见,我显示按钮刷新令牌。

    我希望这可以帮助/指导您解决问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-12-31
      • 1970-01-01
      • 1970-01-01
      • 2016-11-13
      • 2023-03-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多