Google INVISIBLE reCaptcha + jQuery validate()问题

时间:2017-03-11 20:07:35

标签: jquery validation recaptcha invisible

我已经成功地在几个站点上实现了新的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>

6 个答案:

答案 0 :(得分:7)

我遇到了同样的问题,我终于找到了将jquery验证与隐形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,如 隐形重新执行还没有被执行,我们称之为grecaptcha.execute()。 谷歌的重新验证需要几秒钟才能验证,以及何时 它已经完全验证了它会调用formSubmit回调(虽然这个回调没有被调用,但是我们无法将表单数据发送到服务器!)。
  2. 在formSubmit回调中,我们调用$(&#39;#orderform&#39;)。提交强制进入 再次提交提交者。
  3. 再次在submitHandler中,这次是 grecaptcha.getResponse不为null,我们可以将表单数据发布到 服务器,它将包括recaptcha隐藏字段,然后必须 在服务器端验证。
  4. 希望这有帮助。

答案 1 :(得分:6)

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

以下是步骤:

在表单

中的提交按钮之前添加此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方法中执行所有验证,如果所有验证都成功,则执行验证码。

答案 2 :(得分:0)

我在使用经典的Asp.Net Core MVC模板时遇到了同样的问题。 它由Unobstrusive Validation内部装饰。 插入Invisible recaptcha后,验证被破坏。 阅读本文,我设法使用集成验证使其工作,而无需为每个字段指定验证(由Model Class推断为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>

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

答案 3 :(得分:0)

从技术上讲,我们所有人都真的&#34;想要做的是以编程方式将挑战绑定到按钮。例如:

添加此方法,我们只想执行隐形grecaptcha而不是&#34; real&#34;验证

 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="" >

现在,&#34;技术上&#34;提交按钮绑定到用户的点击操作

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

答案 4 :(得分:0)

对我有用的是使用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>

答案 5 :(得分:0)

我在使用.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;
}