带有 jQ​​uery 验证插件的新 reCaptcha

Posted

技术标签:

【中文标题】带有 jQ​​uery 验证插件的新 reCaptcha【英文标题】:New reCaptcha with jQuery Validation Plugin 【发布时间】:2015-06-16 07:31:40 【问题描述】:

在表单提交之前,我搜索并无法弄清楚如何validate the new reCaptcha,以及jQuery validation Plugin的验证功能。

我的意图:

    $.validator.addMethod('reCaptchaMethod', function (value, element, param) 
            if (grecaptcha.getResponse() == '')
                return false;
             else 
                // I would like also to check server side if the recaptcha response is good
                return true
            
        , 'You must complete the antispam verification');


    $("#form").validate(
            rules: 
                name: 
                    required: true,
                    minlength: 2
                ,
                email: 
                    required: true,
                    email: true
                ,
                reCaptcha: 
                    reCaptchaMethod: true   
                
            ,
            messages: 
                name: "Please fill your name",
                email: "Please use a valid email address"
            ,
            submitHandler : function () 
                        $.ajax(
                            type : "POST",
                            url : "sendmail.php",
                            data : $('#form').serialize(),
                            success : function (data) 
                                $('#message').html(data);
                            
                        );
                    


        );

简而言之:我想用remote method检查服务器端,如果用户在提交表单之前通过了recaptcha验证,以及其他验证规则。

我能够检查recaptcha AFTER 提交(在sendmail.php 上),但最好将recaptcha 验证响应与其他字段验证一起进行。

主要原因是为了更好的用户体验,同时检查所有字段。

我已经成功实现了这一点,将检查移到了 submitHandler 中:

            submitHandler : function () 
                  if (grecaptcha.getResponse() == '')
                      // if error I post a message in a div
                      $( '#reCaptchaError' ).html( '<p>Please verify youare human</p>' );

                   else 

                        $.ajax(
                            type : "POST",
                            url : "sendmail.php",
                            data : $('#form').serialize(),
                            success : function (data) 
                                $('#message').html(data);
                            
                        );
                    

             

但我不喜欢这种方法,原因有两个:

    它只是检查recaptcha是否已填写,而不是它是否有效,并且 用户感觉这是一个两步验证。

In this answer 他们说可以在回调中呈现 Recaptcha,以在成功的 CAPTCHA 响应上指定函数调用。

我试图实现这一点,但我无法在 validate() 函数的规则中使用此解决方案。

【问题讨论】:

从客户端验证 recaptcha 响应是否安全?你如何包括secret_key?与验证服务器端相比有什么优势? 【参考方案1】:

我今天在这个问题上苦苦挣扎,最终选择了:

<form onsubmit="return $(this).valid() && grecaptcha.getResponse() != ''">

这感觉就像是最简单的方法。肯定有人会抱怨像这样将 js 内联,但我可以接受。

【讨论】:

问题是我想将验证码验证与 jQuery .Validate() 功能集成,所以我可以在填写字段时向用户显示一个错误列表。抱歉,我不明白如何使用您的解决方案来实现这一目标? 可以通过调用函数来实现。像
然后在脚本标签中你可以调用它并且可以做你的东西 function validateForm() //在这里做代码
这对我有帮助,感谢@pguardiario 提供了这个漂亮的解决方案【参考方案2】:

我知道这个问题有点过时了,但我遇到了同样的问题,刚刚找到了解决方案。 您可以通过在 reCaptcha div 旁边添加一个隐藏字段来做到这一点,例如:

<div class="g-recaptcha" data-sitekey="YOUR-SITE-KEY-HERE"></div>
<input type="hidden" class="hiddenRecaptcha required" name="hiddenRecaptcha" id="hiddenRecaptcha">

然后在你的javascript中:

$("#form").validate(
        ignore: ".ignore",
        rules: 
            name: 
                required: true,
                minlength: 2
            ,
            email: 
                required: true,
                email: true
            ,
            hiddenRecaptcha: 
                required: function () 
                    if (grecaptcha.getResponse() == '') 
                        return true;
                     else 
                        return false;
                    
                
            
        ,(...rest of your code)

注意,您必须在代码中拥有ignore: ".ignore",因为 jquery.validate 默认情况下会忽略隐藏字段,而不是验证它们。

如果要删除 reCapcha validate 上的错误消息,请向 reCapcha 元素添加数据回调

<div class="g-recaptcha" data-sitekey="YOUR-SITE-KEY-HERE" data-callback="recaptchaCallback"></div>

然后在你的js文件中添加

function recaptchaCallback() 
  $('#hiddenRecaptcha').valid();
;

【讨论】:

太棒了!非常简单,工作完美,谢谢。 只是添加,确保不要将您的 recaptchaCallback() 放入准备好的文档中。数据回调事件无法访问。 是否需要规则的函数在无效时返回true??没关系吗? @Phoenix_uy 抱歉延迟回复。是的,这是正确的,如果验证码答案无效,您必须声明隐藏字段是必需的,才能显示错误 用户如何看到验证错误消息?我正在运行验证功能,但 UI 中没有任何变化【参考方案3】:

我发现您的解决方案很有趣 (@FabioG)。

但是,我自己修改了一下,也愿意分享代码给别人使用。

我正在制作一个交互式表单,该表单会在您完成步骤时进行验证。

它用于订购食物。因此,表单需要验证和激活注册按钮,并且它使用的是迄今为止最新的 reCaptcha(2016 年 5 月 12 日)。

此外,此代码处理过期的 reCaptcha,通过 ajax 进行服务器端验证(虽然不包括在内 - 如果有人需要它,请随时评论我的答案,我会相应地对其进行编辑)。

让我们开始吧。

HTML 代码:

<form id="registerForm" method="get" action="">
<fieldset class="step-1">
<h4>Step One:</h4>
<span class="clock">Register under one minute!</span>
<label for="email-register" class="label">E-mail*</label>
<input id="email-register" name="email-register" type="email" value="" autocomplete="off"/>

<label for="password-register" class="label">Password*</label>
<input id="password-register" name="password-register" type="password" value="" autocomplete="off"/>

<div class="g-recaptcha" data-sitekey="6LeS4O8SAAAAALWqAVWnlcB6TDeIjDDAqoWuoyo9" data-callback="recaptchaCallback" data-expired-callback="recaptchaExpired" style="margin-top: 3rem;"></div>
<input id="hidden-grecaptcha" name="hidden-grecaptcha" type="text" style="opacity: 0; position: absolute; top: 0; left: 0; height: 1px; width: 1px;"/>
</div>
</fieldset>
<fieldset class="step-2">
<h4>Step two:</h4>
<span class="notice">All fields with a sign are required!*</span>
<label for="first-name" class="label">First Name*</label>
<input name="first-name" id="first-name" type="text" value="" />

<label for="last-name" class="label">Last Name*</label>
<input name="last-name" id="last-name" type="text" value="" />

<label for="address" class="label">Address*</label> 
<input name="address" id="address" type="text" value=""/>

<label for="entrance" class="label">Entrance</label>    
<input name="entrance" id="entrance" type="text" value=""/>

<label for="apartment-number" class="label">Apartment #</label>
<input name="apartment-number" id="apartment-number" type="text" value="" />

<label for="inter-phone" class="label">Interphone</label>           
<input name="inter-phone" id="inter-phone" type="text" value=""/>

<label for="telephone" class="label">Mobile Number*</label>
<input name="telephone" id="telephone" type="text" value="" />

<label for="special-instructions" class="label">Special Instructions</label>    
<textarea name="special-instructions" id="special-instructions"></textarea>
<div>
</fieldset>
<button class="button-register" disabled>Register</button>
</form>

如您所见,提交按钮(“.button-register”)最初是禁用的。

您只能通过填写必填 (*) 字段来启用它。

请记住,我没有包含任何 CSS。该表格是最低限度的,仅用于教育目的。

很少有与@FabioG 不同的地方,答案是:

无需隐藏元素或使用“.ignore”。我已经用内联 CSS 隐藏了它。

成功的reCaptcha和过期的reCaptcha都有一个响应回调

因此,如果您的 reCaptcha 在填写表单时过期,它将使其无效并且该按钮将再次禁用

同样,表单使用输入字段(隐藏输入字段)将信息传递到 AJAX(稍后将介绍 PHP)并在服务器端验证它 (这是一个潜在的安全风险,我已经介绍了更多)在正文的末尾)。

让我们继续讨论 JavaScript/jQuery。

JavaScript/jQuery:

function debounce(func, wait, immediate) 
    var timeout;
    return function() 
        var context = this, args = arguments;
        var later = function() 
            timeout = null;
            if (!immediate) func.apply(context, args);
        ;
        var callNow = immediate && !timeout;
        clearTimeout(timeout);
        timeout = setTimeout(later, wait);
        if (callNow) func.apply(context, args);
    ;
;
function recaptchaCallback() 
    var response = grecaptcha.getResponse(),
        $button = jQuery(".button-register");
    jQuery("#hidden-grecaptcha").val(response);
    console.log(jQuery("#registerForm").valid());
    if (jQuery("#registerForm").valid()) 
        $button.attr("disabled", false);
    
    else 
        $button.attr("disabled", "disabled");
    


function recaptchaExpired() 
    var $button = jQuery(".button-register");
    jQuery("#hidden-grecaptcha").val("");
    var $button = jQuery(".button-register");
    if (jQuery("#registerForm").valid()) 
        $button.attr("disabled", false);
    
    else 
        $button.attr("disabled", "disabled");
    

function submitRegister() 
  //ajax stuff

(function ($, root, undefined) 
    $(function () 
        'use strict';
        jQuery("#registerForm").find("input").on("keyup", debounce(function() 
          var $button = jQuery(".button-register");
          if (jQuery("#registerForm").valid()) 
            $button.attr("disabled", false);
          
          else 
            $button.attr("disabled", "disabled");
          
        , 1000));
        jQuery("#registerForm").validate(
          rules: 
            "email-register": 
              required: true,
              email: true
            ,
            "password-register": 
              required: true,
              minlength: "6"
            ,
            "first-name": "required",
            "last-name": "required",
            address: "required",
            telephone: "required",
            "hidden-grecaptcha": 
              required: true,
              minlength: "255"
            
          ,
          messages: 
            "email-register": "Enter valid e-mail address",
            "password-register": 
              required: "Enter valid password",
              minlength: "Password must be bigger then 6 chars!"
            ,
            "first-name": "Required!",
            "last-name": "Required!",
            address: "Required!",
            telephone: "Required!"
          ,
          submitHandler: submitRegister
        );
    ); 
)(jQuery, this);

正如您在此处看到的,有几个函数:recaptchaCallback()recaptchaExpired()

recaptchaCallback() 通过数据属性 data-callback 嵌入,使用 grecaptcha.getResponse() 来查看 reCaptcha被验证,如果是,它将令牌输入到隐藏的输入字段并通过 jQuery("#registerForm).validate(); 请求重新验证。

但是,如果 reCaptcha 同时过期,它将使用“data-expired-callback”中分配的函数,从输入字段中删除令牌并再次要求重新验证,这将失败,因为该字段是空的。这是通过 recaptchaExpired() 函数实现的。

在后面的代码中,您可以看到我们添加了一个 jQuery keyup 函数,用于检查重新验证并查看用户是否已将所需信息传递给输入字段。如果信息和字段验证成功,keyup 功能将启用 Register 按钮。

另外,我在 keyup 上使用了去抖动脚本(tnx,David Walsh)。所以它不会导致浏览器延迟。因为,会有很多打字。

但是,请记住,如果用户决定绕过 reCaptcha,他总是可以在输入字段中输入“255”字符长字符串。但是,我更进一步,做了一个 AJAX 验证服务器端来确认 reCaptcha。不过,我没有将其包含在答案中。

我认为这段代码比之前的答案略有改进。如果您有任何问题或需要 AJAX/PHP 代码,请随时发表评论。有空我会提供的。

这里还有 codepen:reCaptcha with jQuery.validation

您可以在其 API 中找到有关 reCatpcha 数据属性和函数的所有信息:reCaptcha API

希望它对某人有所帮助!

问候,

【讨论】:

【参考方案4】:

您还可以在submitHandler

中阻止表单提交
$("#loginForm").validate(
rules: 
    username: 
        required: true,
        minlength: 6
    ,
    password: 
        required: true,
    ,
,
submitHandler: function(form) 
    if (grecaptcha.getResponse()) 
        form.submit();
     else 
        alert('Please confirm captcha to proceed')
    

);

【讨论】:

嗨 Ranjith,我使用的是相同的代码,但为 form.submit();我正在使用 ajax 代码。这个怎么用? @NarenVerma 代替 form.submit();把你的ajax代码

以上是关于带有 jQ​​uery 验证插件的新 reCaptcha的主要内容,如果未能解决你的问题,请参考以下文章

带有 jQ​​uery 验证的 ASP.Net MVC Ajax 表单

使用带有 jQ​​uery 插件的 Browserify

使用带有 jQ​​uery 不显眼验证的 HTML-5 验证弹出窗口

带有 jQ​​uery 的类似狮子的滚动条?

带有 jQ​​uery UI 可排序的 Knockoutjs

带有 jQ​​uery DataTables 和服务器端数据加载的 ASP.Net Webforms GridView