【问题标题】:Google INVISIBLE reCaptcha + jQuery validate() issueGoogle INVISIBLE reCaptcha + jQuery validate() 问题
【发布时间】:2017-08-02 01:50:42
【问题描述】:

我已经在几个站点上成功地实现了新的Google's INVISIBLE reCaptcha,但是它与 jQuery validate() 冲突,因此 js 验证不再在按钮/表单提交时执行,并且 reCaptcha 立即启动。如果用户忘记填写所需的表单字段,则必须等待服务器响应,然后再返回。

jQuery .validate() 支持回调,但由于它是在 CMS 的内部类中硬编码的,有没有办法可以在外部以某种方式修改它(例如,从前端主题,在文档中加载,当验证码已经渲染时)?

或者,另一个想法是以某种方式推迟验证码的回调,以便验证步骤有机会运行。

谢谢!

jQuery 验证表单:(硬编码在核心中,无法修改,除非我编辑核心文件或扩展类/克隆功能 - 不是最佳的)

<script type="text/javascript">
$(document).ready(function(){
    $("form[name=comment_form]").validate({
        rules: {
            body: {
                required: true,
                minlength: 1
            },
            authorEmail: {
                required: true,
                email: true
            }
        },
        wrapper: "li",
        errorLabelContainer: "#comment_error_list",
        invalidHandler: function(form, validator) {
            $('html,body').animate({ scrollTop: $('#comment_error_list').offset().top }, { duration: 250, easing: 'swing'});
        },
        submitHandler: function(form){
            $('button[type=submit], input[type=submit]').attr('disabled', 'disabled');
            form.submit();
        }
    });
});
</script>

reCaptcha 显式渲染:

<script type='text/javascript'>
    var renderInvisibleReCaptcha = function() {
    for (var i = 0; i < document.forms.length; ++i) {
        var form = document.forms[i];
        var holder = form.querySelector('.invisible-recaptcha');
        if (null === holder) continue;
        (function(frm){
            var holderId = grecaptcha.render(holder, {
            'sitekey': 'my-key-here',
            'badge': 'inline',
            'size': 'invisible',
            'callback': function (recaptchaToken) {HTMLFormElement.prototype.submit.call(frm);},
            'expired-callback': function(){grecaptcha.reset(holderId);}
            });
            frm.onsubmit = function (evt){evt.preventDefault();grecaptcha.execute(holderId);};
        })(form);
    }
};
</script>

【问题讨论】:

  • 您可能想先尝试验证表单——当它被验证为有效时(没有验证码部分),您以编程方式调用 reCAPTCHA:developers.google.com/recaptcha/docs/…
  • 嗨,特里,谢谢,但如果我知道,我就不会问这个问题了 :) 看起来很简单,当然,但不确定如何绑定表单验证的结果并调用验证码。跨度>
  • 看起来validate() 所做的只是添加了几个事件处理程序。尝试使用$('.form').off('submit')$('.submit-button').off('click'); 清除它们。我会发布一个明确的答案,但目前无法设置小提琴来检查......
  • 不确定是什么想法,但快速测试 - 似乎没有任何区别。
  • @dev101 你找到这个问题的解决方案了吗?

标签: jquery validation recaptcha invisible


【解决方案1】:

我遇到了同样的问题,我终于找到了将 jquery validate 与不可见的 reCaptcha 集成的正确方法。这是这里提出的一些解决方案的混合。

首先,HTML部分:

<div class="g-recaptcha" data-sitekey="<your key here>"
    data-size="invisible" 
    data-callback="formSubmit">
</div>

那么,你必须以这种方式实现 reCaptcha 回调:

function formSubmit(response) {
    // submit the form which now includes a g-recaptcha-response input
     $("#orderform").submit();
    return true;
}

最后,棘手的部分在 jquery validate 的 submitHandler 中:

   submitHandler: function (form) {
        if (grecaptcha.getResponse()) {
                // 2) finally sending form data
                form.submit();
        }else{
                // 1) Before sending we must validate captcha
            grecaptcha.reset();
            grecaptcha.execute();
        }           
    }

顺序如下:

  1. 当用户点击提交按钮时,jquery 的 submitHandler 被调用,如 不可见的 recaptcha 尚未执行,我们调用 grecaptcha.execute()。 谷歌的recaptcha需要几秒钟来验证,什么时候 完全验证它会调用 formSubmit 回调(虽然没有调用此回调,但我们无法将表单数据发送到服务器!)。
  2. 在formSubmit回调中我们调用$('#orderform').submit强制进入 再次提交处理程序。
  3. 再次在 submitHandler 内部,这次是 grecaptcha.getResponse 不为空,我们可以将表单数据发布到 服务器,它将包括recaptcha隐藏字段,然后必须 在服务器端进行验证。

希望这会有所帮助。

【讨论】:

  • 我认为div 需要关闭&lt;/div&gt; 标签。
  • 我不能让它工作,这是我的提交处理程序: $("form[name='contact']").submit(function(event){ //几乎和你的,除了我在 else } 中添加了一个 event.preventdefault 知道为什么它对我不起作用吗?我必须按两次提交才能让它起作用 FYI
【解决方案2】:

在 Terry 提供的 link 的帮助下,我在执行 invisible reCaptcha 之前遇到了类似的问题并验证了表单。

步骤如下:

在表单中的提交按钮之前添加这个 div

 <div id='recaptcha' class="g-recaptcha"
      data-sitekey="your_site_key"
      data-callback="onSubmit"
      data-size="invisible"></div>

同时更新您的密钥。 在表单关闭之后添加这个方法

<script>onload();</script>

在您的表单之前添加此代码

<script>
function validate(event) {
 event.preventDefault();
 if (!document.getElementById('field').value) {
   alert("You must add text to the required field");
 } else {
   grecaptcha.execute();
 }
}

function onload() {
 var element = document.getElementById('submit');
 element.onclick = validate;
}
</script>
<script src="https://www.google.com/recaptcha/api.js" async defer></script>

在 validate 方法中进行所有验证,如果所有验证都成功,则执行验证码。

【讨论】:

  • 感谢您的回答,我会试一试,但是,由于多种形式,我必须使用显式渲染。手动添加验证码 div 持有者的顶部将需要不同的实现。
  • 当然,如果您也需要有关多种表格的帮助,请告诉我。另外,发布您的多种形式的解决方案。
  • 对不起,不能接受这个作为答案,因为它没有回答原来的问题:1)没有ID,只有名字; 2) 使用显式渲染; 3)阅读问题描述中的附加条件。如果您发布原始问题的答案,我会很乐意接受它,但这是对我没有问过的完全不同的问题的答案。希望你能理解。
【解决方案3】:

从技术上讲,我们“真正”想要做的就是以编程方式将挑战绑定到按钮。例如:

添加这个方法,我们只想执行不可见的 grecaptcha 而不是“真正的”验证

 jQuery.validator.addMethod("iv_recapcha_valid", function(value, element) {
        return grecaptcha.execute();
    }, 'No message needed, grecaptcha excecuted'); 

然后将此规则添加到您现有的规则中

rules: { gRecaptchaResponse: { iv_recapcha_valid: true } }

添加隐藏字段

<input type="hidden" name="gRecaptchaResponse" value="" >

现在,“技术上”,提交按钮绑定到用户的点击操作

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

【讨论】:

    【解决方案4】:

    我在使用经典 Asp.Net Core MVC 模板时遇到了同样的问题。 它在内部由 Unobtrusive Validation 装饰。 插入 Invisible recaptcha 后,验证被破坏。 阅读这篇文章,我设法使它工作,使用集成验证,而不需要为每个字段指定验证(由模型类推断到 MVC 项目中)

    HTML 页面:

     <input type="hidden" name="gRecaptchaResponse" id="gRecaptchaResponse" value="" /> 
    
                <div class="form-group">
                    <div class="col-md-offset-2 col-md-10">
                        <div id='recaptcha' class="g-recaptcha"
                             data-sitekey="@_configuration["InvisibleRecaptcha:SiteKey"]"
                             data-callback="SubmitRegistration"
                             data-size="invisible"></div>
                        <button type="submit" id="SubmitButton" class="btn btn-primary"> Invia</button>
                    </div>
                </div>
    

    Javascript 代码:

     <script>
    
            function onload() {
                var element = document.getElementById('SubmitButton');
                element.onclick = validate;
            }
            onload();
    
            function validate(event) {
                event.preventDefault();
    
                $("#Form").validate();
                var isFormValid = $("#Form").valid();
                if (isFormValid) {
                    grecaptcha.execute();
                }
            }
    
            function SubmitRegistration(data) {
                if ($("#gRecaptchaResponse").val() == '') {
                    $("#gRecaptchaResponse").val(data);
                }
                document.getElementById("Form").submit();
            }  
    
        </script>
    

    希望这段代码可以帮助到某人

    【讨论】:

      【解决方案5】:

      对我有用的是使用 jquery 来选择表单(我一直在使用 getElementByID),然后“返回 true”。所以不要这样:

              <script src="https://www.google.com/recaptcha/api.js" async defer></script>
              <script>
                  function onSubmit(token) {
                      document.getElementById("frm").submit();
                  }
              </script>
              <button class="g-recaptcha btn btn-block btn-primary" data-sitekey="<YOUR_KEY>" data-callback='onSubmit'>Submit</button>
      

      使用这个:

              <script src="https://www.google.com/recaptcha/api.js" async defer></script>
              <script>
                  function onSubmit(token) {
                      $("#frm").submit();
                      return true;
                  }
              </script>
              <button class="g-recaptcha btn btn-block btn-primary" data-sitekey="<YOUR_KEY>" data-callback='onSubmit'>Submit</button>
      

      【讨论】:

        【解决方案6】:

        我在使用 .NET Razor Pages 时遇到了这个问题,它默认使用 jquery 验证。上面的大多数解决方案都是手动调用验证码。我想使用Automatic Binding to a Button 方法。这将导致验证码首先运行,如果我们成功获得验证码令牌,那么我将运行 jquery 验证并可能提交表单。默认情况下,这种自动绑定方法会破坏 jquery 验证触发器。

        为验证码设置按钮

        <button type="submit" class="btn primary-btn g-recaptcha h-100"
                                data-callback='onSubmit'
                                data-sitekey='@Model.CaptchaKey'
                                data-error-callback="onCaptchaError"
                                data-badge="inline"
                                data-action='submit'>
                            Submit <i class="fas fa-chevron-right"></i>
                        </button>
        

        处理验证码事件以判断成功/失败

        <script src="https://www.google.com/recaptcha/api.js"></script>
        <script>
            function onSubmit(token) {
                //Once we get a valid Captcha code, let's verify the form's unobtrusive validation
                $("#your-form-id").validate();
                var validationResult = $("#your-form-id").valid();
                if (validationResult) {
                    //If we are valid, submit!  Otherwise errors will show and we don't want to submit
                    document.getElementById("your-form-id").submit();
                }
            }
        
            function onCaptchaError() {
                alert("We had some trouble accessing captcha resources.  Please refresh the page and try again.");
            }
        
        </script>
        

        额外功劳:设置验证码徽章的样式 不过请确保您关注Google's policies on this

        .grecaptcha-badge {
            visibility: hidden;
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-11-16
          • 1970-01-01
          相关资源
          最近更新 更多