简体   繁体   English

如何使用 Google ReCaptcha V2 Invisible AND Multiple Forms 执行 HTML 表单验证?

[英]How do I perform HTML form validation with Google ReCaptcha V2 Invisible AND Multiple Forms?

I have 2 forms on a page that both need Google ReCaptcha V2 Invisible.我在页面上有 2 个表单,它们都需要 Google ReCaptcha V2 Invisible。 I have this working perfectly using the following code.我使用以下代码完美地工作。

In the Header:在标题中:

<script src='https://www.google.com/recaptcha/api.js?onload=myCallBack&render=explicit' async defer></script>

Here is the form.这是表格。 Pretty simple.很简单。 You can see the ReCaptcha is tied to the button, and that it has a unique callback and ID.您可以看到 ReCaptcha 与按钮相关联,并且它具有唯一的回调和 ID。

<form id="subForm" action="form-processing.php" method="POST">         
    <input placeholder="Name" id="name" name="fname" type="text" required/>
    <input placeholder="Email" id="email" name="email" type="text" required/>
    <textarea placeholder="Comments" id="comments" cols="30" name="comments" rows="6" required></textarea>

    <button class="g-recaptcha form-submit-button" data-sitekey="MySiteKey" data-callback="captchaSubmit2" id="recaptcha2">Submit</button>
</form>

When the ReCaptcha api in the header loads, and fires off the onload callback (myCallBack) the following code is called to render the ReCaptcha on each of the form's buttons.当标题中的 ReCaptcha api 加载并触发 onload 回调 (myCallBack) 时,将调用以下代码以在表单的每个按钮上呈现 ReCaptcha。

var recaptcha1;
var recaptcha2;
var myCallBack = function() {
    //Render recaptcha1 on element with ID "recaptcha1"
    recaptcha1 = grecaptcha.render('recaptcha1', {
      'sitekey' : 'MySiteKey',
      'theme' : 'light'
    });

    //Render recaptcha2 on element with ID "recaptcha2"
    recaptcha2 = grecaptcha.render('recaptcha2', {
      'sitekey' : 'MySiteKey',
      'theme' : 'light'
    });
};

And finally, when a submit button is clicked, ReCaptcha processes, and uses the callback specified on the button to trigger the actual form submission.最后,当点击提交按钮时,ReCaptcha 处理并使用按钮上指定的回调来触发实际的表单提交。

function captchaSubmit1(data) {
    document.getElementById("mainForm").submit();
}
function captchaSubmit2(data) {
    document.getElementById("subForm").submit();
}

On the backend in my server-side processing I am using the following code to verify the ReCaptcha.在服务器端处理的后端,我使用以下代码来验证 ReCaptcha。

<?php
    // reCaptcha info
    $secret = "MySecretKey";
    $remoteip = $_SERVER["REMOTE_ADDR"];
    $url = "https://www.google.com/recaptcha/api/siteverify";

    // Form info
    $first = $_POST["first"];
    $last = $_POST["last"];
    $response = $_POST["g-recaptcha-response"];

    // Curl Request
    $curl = curl_init();
    curl_setopt($curl, CURLOPT_URL, $url);
    curl_setopt($curl, CURLOPT_POST, true);
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($curl, CURLOPT_POSTFIELDS, array(
        'secret' => $secret,
        'response' => $response,
        'remoteip' => $remoteip
        ));
    $curlData = curl_exec($curl);
    curl_close($curl);

    // Parse data
    $recaptcha = json_decode($curlData, true);
    if ($recaptcha["success"])
    { 
       /// MY DATA VALIDATION & EMAILING OF FORM DATA ///
    }else{
        header('Location: /thank-you-for-contacting-us/?gvx');
        exit;
    }
?>

If the form validation fails due to Google ReCaptcha verify failure, it simply redirects to the thank you page with a code so I know it was the recaptcha that failed.如果表单验证由于 Google ReCaptcha 验证失败而失败,它只是重定向到带有代码的感谢页面,所以我知道这是失败的 recaptcha。 There is a separate code if the form field data fails validation.如果表单字段数据未通过验证,则有一个单独的代码。 Just a way to help me see what is going on.只是一种帮助我了解正在发生的事情的方法。

OK!好的! so now the problem is that these forms do not perform the HTML client-side field validation.所以现在的问题是这些表单不执行 HTML 客户端字段验证。 I have tried to incorporate this solution with no luck: How to run reCaptcha ONLY if HTML5 validation has passed?我试图合并这个解决方案但没有运气: How to run reCaptcha ONLY if HTML5验证通过?

These bits of code are the main take-aways from that article.这些代码是那篇文章的主要内容。 I replaced the submit button:我更换了提交按钮:

Before:前:

<button class="g-recaptcha form-submit-button" data-sitekey="MySiteKey" data-callback="captchaSubmit2" id="recaptcha2">Submit</button>

After:后:

<button class="form-submit-button" type="submit">Submit</button>

And I added this div into the form just above the submit button:我将这个 div 添加到提交按钮上方的表单中:

<div id="recaptcha2" class="g-recaptcha" 
data-sitekey="MySiteKey"
data-size="invisible"
data-callback="captchaSubmit2">

And these are the new handlers for the form submit:这些是表单提交的新处理程序:

$('#mainForm').submit(function (event) {
    if (!grecaptcha.getResponse()) {
        event.preventDefault(); //prevent form submit
        grecaptcha.reset();
        grecaptcha.execute();
    } 
});
$('#subForm').submit(function (event) {
    if (!grecaptcha.getResponse()) {
        event.preventDefault(); //prevent form submit
        grecaptcha.reset();
        grecaptcha.execute();
    } 
});

So the final flow here is that page loads the api, the api calls the recaptcha render that renders the recaptcha on the g-recaptcha div, the form is submitted, the default behavior is prevented allowing the HTML validation to function (Which it does), and when the form actually does submit, it triggers the above function to call grecaptcha.execute();所以这里的最终流程是页面加载 api,api 调用在 g-recaptcha div 上呈现 recaptcha 的 recaptcha 呈现器,提交表单,阻止默认行为,允许 HTML 验证起作用(它这样做) ,当表单真正提交时,它会触发上述函数调用 grecaptcha.execute(); which processes, and when it completes, calls the callback function tied to it (captchaSubmit2) which does the real final submit.哪个进程,当它完成时,调用绑定到它的回调函数 (captchaSubmit2),它执行真正的最终提交。 Then my server-side script is failing google validation, and sadness ensues...然后我的服务器端脚本没有通过谷歌验证,悲伤随之而来......

I've spent two days beating on this now, with the usual "Is it done yet?"我现在已经花了两天时间来解决这个问题,通常的“完成了吗?” echoing from above.从上面回响。 I am so close I can taste it, but I am obviously missing something.我离我很近,我可以尝到它的味道,但我显然错过了一些东西。

I just need Google ReCaptcha V2 Invisible working on 2 forms on the same page with HTML form validation for required fields.我只需要 Google ReCaptcha V2 Invisible 在同一页面上处理 2 个表单,并对必填字段进行 HTML 表单验证。

Any help would be very much appreciated.任何帮助将不胜感激。

After a lot of searching, I finally found a solution that works and is rather elegant in the fact that it supports multiple forms on a single page, and is dynamic.经过大量搜索,我终于找到了一个有效且相当优雅的解决方案,因为它支持单个页面上的多种表单,并且是动态的。 It searches the page and attaches the recaptcha to any matching tagged divs.它搜索页面并将 recaptcha 附加到任何匹配的标记 div。 It should support as many forms as you like on one page.它应该在一页上支持尽可能多的表单。

This is the tag it attaches to:这是它附加的标签:

<div class="recaptcha-holder"></div>

I am still unsure why my own implementation did not work.我仍然不确定为什么我自己的实现不起作用。 Every time I had recaptcha attached to multiple forms, the server-side processing would fail, and debugging showed it was not receiving recaptcha data.每次我将 recaptcha 附加到多个表单时,服务器端处理都会失败,并且调试显示它没有收到 recaptcha 数据。

Just a note, this is being implemented on a WordPress site, so I am adding the javascript to my existing js include that I put my custom code in.请注意,这是在 WordPress 网站上实现的,所以我将 javascript 添加到我现有的 js 包含中,我将自定义代码放入其中。

This code is the last entry on this question ( Implement the new Invisible reCaptcha from Google ) posted by Mch ( https://stackoverflow.com/users/7327512/mch ).此代码是Mch ( https://stackoverflow.com/users/7327512/mch ) 发布的有关此问题的最后一个条目( 从 Google 实现新的 Invisible reCaptcha )。 All thanks goes to them for the front-end solution.感谢他们提供的前端解决方案。 Funny enough it was posted at the very end of 2016.有趣的是,它是在 2016 年底发布的。

Mch's Front-End Example Mch 的前端示例

<!DOCTYPE html>
<html>
<body>

<form action="" method="post">
    <input type="text" name="first-name-1"> <br />
    <input type="text" name="last-name-1"> <br />

    <div class="recaptcha-holder"></div>

    <input type="submit" value="Submit">
</form>

<br /><br />

<form action="" method="post">
    <input type="text" name="first-name-2"> <br />
    <input type="text" name="last-name-2"> <br />

    <div class="recaptcha-holder"></div>

    <input type="submit" value="Submit">
</form>
<script src="https://www.google.com/recaptcha/api.js?onload=renderGoogleInvisibleRecaptcha&render=explicit" async defer></script>
</body>
</html>

Mch's Javascript (Added to my existing JS include) Mch 的 Javascript(添加到我现有的 JS 包括)

  var renderGoogleInvisibleRecaptcha = function() {
    for (var i = 0; i < document.forms.length; ++i) {
      var form = document.forms[i];
      var holder = form.querySelector('.recaptcha-holder');
      if (null === holder){
        continue;
      }

      (function(frm){

        var holderId = grecaptcha.render(holder,{
          'sitekey': 'CHANGE_ME_WITH_YOUR_SITE_KEY',
          'size': 'invisible',
          'badge' : 'bottomright', // possible values: bottomright, bottomleft, inline
          'callback' : function (recaptchaToken) {
            HTMLFormElement.prototype.submit.call(frm);
          }
        });

        frm.onsubmit = function (evt){
          evt.preventDefault();
          grecaptcha.execute(holderId);
        };

      })(form);
    }
  };

And finally my Back-End (server side) processing:最后我的后端(服务器端)处理:

<?php
    // reCaptcha info
    $secret = "MySecretKey";
    $remoteip = $_SERVER["REMOTE_ADDR"];
    $url = "https://www.google.com/recaptcha/api/siteverify";

    // Form info
    $first = $_POST["first"];
    $last = $_POST["last"];
    $response = $_POST["g-recaptcha-response"];

    // Curl Request
    $curl = curl_init();
    curl_setopt($curl, CURLOPT_URL, $url);
    curl_setopt($curl, CURLOPT_POST, true);
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($curl, CURLOPT_POSTFIELDS, array(
        'secret' => $secret,
        'response' => $response,
        'remoteip' => $remoteip
        ));
    $curlData = curl_exec($curl);
    curl_close($curl);

    // Parse data
    $recaptcha = json_decode($curlData, true);
    if ($recaptcha["success"])
    { 
        // MY DATA VALIDATION & EMAILING OF FORM DATA
    }else{
        // Google ReCaptcha Failed to Verify - Send to False Positive
        header('Location: /thank-you-for-contacting-us/?gvx');
        exit;
    }
?>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM