如何使用 Google ReCaptcha V2 Invisible AND Multiple Forms 执行 HTML 表单验证?
How do I perform HTML form validation with Google ReCaptcha V2 Invisible AND Multiple Forms?
我在一个页面上有 2 个表单都需要 Google ReCaptcha V2 Invisible。我使用以下代码可以完美地工作。
在Header:
<script src='https://www.google.com/recaptcha/api.js?onload=myCallBack&render=explicit' async defer></script>
这是表格。很简单。您可以看到 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>
当 header 中的 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'
});
};
最后,当提交按钮被点击时,ReCaptcha 进行处理,并使用按钮上指定的回调来触发实际的表单提交。
function captchaSubmit1(data) {
document.getElementById("mainForm").submit();
}
function captchaSubmit2(data) {
document.getElementById("subForm").submit();
}
在我的 server-side 处理的后端,我使用以下代码来验证 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;
}
?>
如果表单验证由于 Google ReCaptcha 验证失败而失败,它只是重定向到带有代码的感谢页面,所以我知道是 recaptcha 失败了。如果表单字段数据验证失败,则有一个单独的代码。只是一种帮助我了解发生了什么的方法。
好的!所以现在的问题是这些表单不执行 HTML client-side 字段验证。我曾尝试合并此解决方案,但没有成功:
这些代码是那篇文章的主要 take-aways。我更换了提交按钮:
之前:
<button class="g-recaptcha form-submit-button" data-sitekey="MySiteKey" data-callback="captchaSubmit2" id="recaptcha2">Submit</button>
之后:
<button class="form-submit-button" type="submit">Submit</button>
然后我将此 div 添加到提交按钮上方的表单中:
<div id="recaptcha2" class="g-recaptcha"
data-sitekey="MySiteKey"
data-size="invisible"
data-callback="captchaSubmit2">
这些是表单提交的新处理程序:
$('#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();
}
});
所以这里的最终流程是页面加载 api,api 调用 recaptcha 呈现器,在 g-recaptcha div 上呈现 recaptcha,表单被提交,默认行为被阻止允许 HTML 验证起作用(它确实如此),并且当表单实际提交时,它触发上述函数调用 grecaptcha.execute();哪个进程,当它完成时,调用与其相关的回调函数 (captchaSubmit2),该回调函数执行真正的最终提交。然后我的 server-side 脚本没有通过 google 验证,悲伤随之而来...
我已经花了两天时间解决这个问题,通常的 "Is it done yet?" 从上面回响。我离它很近,我能尝到它的味道,但我显然错过了什么。
我只需要 Google ReCaptcha V2 Invisible 在同一页面上处理 2 个表单,并对必填字段进行 HTML 表单验证。
非常感谢任何帮助。
经过大量搜索,我终于找到了一个可行的解决方案,并且在支持单个页面上的多个表单并且是动态的方面相当优雅。它搜索页面并将 recaptcha 附加到任何匹配的标记 div。它应该在一页上支持尽可能多的表单。
这是它附加的标签:
<div class="recaptcha-holder"></div>
我仍然不确定为什么我自己的实现不起作用。每次我将 recaptcha 附加到多个表单时,服务器端处理都会失败,并且调试显示它没有接收到 recaptcha 数据。
请注意,这是在 WordPress 网站上实施的,因此我将 javascript 添加到我现有的 js 包含中,我将自定义代码放入其中。
此代码是此问题的最后一个条目 () posted by Mch (https://whosebug.com/users/7327512/mch)。感谢他们提供前端解决方案。有趣的是它是在 2016 年底发布的。
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 的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);
}
};
最后是我的后端(服务器端)处理:
<?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;
}
?>
我在一个页面上有 2 个表单都需要 Google ReCaptcha V2 Invisible。我使用以下代码可以完美地工作。
在Header:
<script src='https://www.google.com/recaptcha/api.js?onload=myCallBack&render=explicit' async defer></script>
这是表格。很简单。您可以看到 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>
当 header 中的 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'
});
};
最后,当提交按钮被点击时,ReCaptcha 进行处理,并使用按钮上指定的回调来触发实际的表单提交。
function captchaSubmit1(data) {
document.getElementById("mainForm").submit();
}
function captchaSubmit2(data) {
document.getElementById("subForm").submit();
}
在我的 server-side 处理的后端,我使用以下代码来验证 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;
}
?>
如果表单验证由于 Google ReCaptcha 验证失败而失败,它只是重定向到带有代码的感谢页面,所以我知道是 recaptcha 失败了。如果表单字段数据验证失败,则有一个单独的代码。只是一种帮助我了解发生了什么的方法。
好的!所以现在的问题是这些表单不执行 HTML client-side 字段验证。我曾尝试合并此解决方案,但没有成功:
这些代码是那篇文章的主要 take-aways。我更换了提交按钮:
之前:
<button class="g-recaptcha form-submit-button" data-sitekey="MySiteKey" data-callback="captchaSubmit2" id="recaptcha2">Submit</button>
之后:
<button class="form-submit-button" type="submit">Submit</button>
然后我将此 div 添加到提交按钮上方的表单中:
<div id="recaptcha2" class="g-recaptcha"
data-sitekey="MySiteKey"
data-size="invisible"
data-callback="captchaSubmit2">
这些是表单提交的新处理程序:
$('#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();
}
});
所以这里的最终流程是页面加载 api,api 调用 recaptcha 呈现器,在 g-recaptcha div 上呈现 recaptcha,表单被提交,默认行为被阻止允许 HTML 验证起作用(它确实如此),并且当表单实际提交时,它触发上述函数调用 grecaptcha.execute();哪个进程,当它完成时,调用与其相关的回调函数 (captchaSubmit2),该回调函数执行真正的最终提交。然后我的 server-side 脚本没有通过 google 验证,悲伤随之而来...
我已经花了两天时间解决这个问题,通常的 "Is it done yet?" 从上面回响。我离它很近,我能尝到它的味道,但我显然错过了什么。
我只需要 Google ReCaptcha V2 Invisible 在同一页面上处理 2 个表单,并对必填字段进行 HTML 表单验证。
非常感谢任何帮助。
经过大量搜索,我终于找到了一个可行的解决方案,并且在支持单个页面上的多个表单并且是动态的方面相当优雅。它搜索页面并将 recaptcha 附加到任何匹配的标记 div。它应该在一页上支持尽可能多的表单。
这是它附加的标签:
<div class="recaptcha-holder"></div>
我仍然不确定为什么我自己的实现不起作用。每次我将 recaptcha 附加到多个表单时,服务器端处理都会失败,并且调试显示它没有接收到 recaptcha 数据。
请注意,这是在 WordPress 网站上实施的,因此我将 javascript 添加到我现有的 js 包含中,我将自定义代码放入其中。
此代码是此问题的最后一个条目 (
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 的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);
}
};
最后是我的后端(服务器端)处理:
<?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;
}
?>