不可见的 google Recaptcha 和 ajax 表单
Posted
技术标签:
【中文标题】不可见的 google Recaptcha 和 ajax 表单【英文标题】:Invisible google Recaptcha and ajax form 【发布时间】:2017-08-09 03:30:54 【问题描述】:我有一个 ajax 表单:
<form id="my_form">
<input type="text" id="field1" />
<input type="submit" value="submit" />
</form>
还有js代码:
document.getElementById("my_form").onsubmit = function(e)
e.preventDefault();
var xhr = new XMLHttpRequest();
//.............. send request to a server
在文档中,它假定表单是普通表单,而不是 ajax。我应该如何将不可见的 reCaptcha 集成到我的 ajax 表单中?例如:
<form id="my_form">
<input type="text" id="field1" />
<div class="g-recaptcha" data-sitekey="12345" data-callback="????></div>
<input type="submit" value="submit" />
</form>
特别是,我应该为“数据回调”处理程序指定什么?同样,在文档中它的 data-callback 提交了一个表单,但是一个普通的表单,而我的是 ajax。我需要“数据回调”吗?我不应该在我的处理程序中调用 recaptcha 吗?怎么样?
有“render”、“getResponse”和“execute”。我应该使用哪一个?从文档中不清楚。
【问题讨论】:
【参考方案1】:您可以使用 jquery 轻松验证 google recaptcha
<?php
$remoteip = $_SERVER['REMOTE_ADDR'];
?>
<script type="text/javascript">
function reloadRecaptcha()
var publicKey = "your_public_key";
var div = "recap";
Recaptcha.create(publicKey,div,theme: "white");
return false;
function validate()
var challenge = Recaptcha.get_challenge();
var response = Recaptcha.get_response();
var remoteip = "<?php echo $remoteip; ?>";
$.ajax(
type: "POST",
url: "validateRecaptcha.php",
async: false,
data:
remoteip: remoteip,
challenge: challenge,
response: response
,
success: function(resp)
if(resp == "true")
document.getElementById("message").innerhtml = "Perfect!";
else
document.getElementById("message").innerHTML = "Incorrect Recaptcha! Please try again!";
reloadRecaptcha();
);
return false;
【讨论】:
有趣的代码,但它缺少信息...Recaptcha
的声明,var div = "recap";
是什么【参考方案2】:
我同意“不可见的”recaptcha 文档不够全面。在了解如何使用它之前,我不得不花一些时间通过代码示例和“可见”recaptcha 的文档进行挖掘。
先说一下recaptcha API:
grecaptcha.render(htmlEl, options, inherit)
是在页面上呈现验证码 HTML 的 JS API 方法。默认情况下,recaptcha 脚本将尝试查找带有class="g-recaptcha
的任何元素并尝试立即渲染,但是可以通过将 ?render=explicit
查询参数附加到 recaptcha 脚本 src url 来覆盖此行为。当您的 recaptcha .g-recaptcha
元素在加载脚本之后的某个时间点附加到 DOM 时,您可能还希望使用此 api 按需呈现 recaptcha html。这个api返回一个ID值,可以传给其他api方法,但是如果不传,那些api的查找和引用页面上的第一个recaptcha。
grecaptcha.getResponse(optional_id)
返回令牌。如果 token 为空字符串,则表示用户尚未通过验证,即用户尚未完成验证码质询。
grecaptcha.execute(optional_id)
api 以编程方式按需触发recaptcha 质询。此 api 仅适用于“不可见”的 recaptcha。当用户点击recaptcha模块时,会触发可见的recaptcha挑战。
grecaptcha.reset(optional_id)
将重置挑战,即每次服务器无法使用 recaptcha api 服务器验证令牌时都必须执行此操作(因为令牌是一次性使用的),但根据您的实施,您可能决定随时重置。
现在,让我们谈谈数据回调:
data-callback
是一个属性,您可以在其中传递全局命名空间函数的名称,即某些可作为 window['nameOfFunction'] 访问的函数。每次使用您最终将传递给服务器的令牌值成功验证用户时,都会调用此回调。这与grecaptcha.getResponse()
返回的令牌相同,因此从技术上讲,您根本不需要此函数。但它可以作为回调,让您知道用户已通过验证,以防您需要更新 UI 或其他东西。
如果出于某种原因您不希望从窗口命名空间访问此回调,您可以将带有callback
键的选项对象中的此方法传递给grecaptcha.render()
。注意:options.callback
可以接受一个字符串值,相当于在 HTML 中传递 data-callback
属性,即它必须是窗口命名空间中的函数。但options.callback
也可以采用“函数”值。
现在是一些示例代码:
HTML
<script src="https://www.google.com/recaptcha/api.js?render=explicit&onload=onScriptLoad" async defer></script>
JS
window.onScriptLoad = function ()
// this callback will be called by recaptcah/api.js once its loaded. If we used
// render=explicit as param in script src, then we can explicitly render reCaptcha at this point
// element to "render" invisible captcha in
var htmlEl = document.querySelector('.g-recaptcha');
// option to captcha
var captchaOptions =
sitekey: '6Lck',
size: 'invisible',
// tell reCaptcha which callback to notify when user is successfully verified.
// if this value is string, then it must be name of function accessible via window['nameOfFunc'],
// and passing string is equivalent to specifying data-callback='nameOfFunc', but it can be
// reference to an actual function
callback: window.onUserVerified
;
// Only for "invisible" type. if true, will read value from html-element's data-* attribute if its not passed via captchaOptions
var inheritFromDataAttr = true;
// now render
recaptchaId = window.grecaptcha.render(htmlEl, captchaOptions, inheritFromDataAttr);
;
// this is assigned from "data-callback" or render()'s "options.callback"
window.onUserVerified = function (token)
alert('User Is verified');
console.log('token=', token);
;
// click handler for form's submit button
function onSubmitBtnClick ()
var token = window.grecaptcha.getResponse(recaptchaId);
// if no token, mean user is not validated yet
if (!token)
// trigger validation
window.grecaptcha.execute(recaptchaId);
return;
var xhrData =
'g-recaptcha-response': token
// more ajax body/data here
;
// proceed with appending more ajax call data to xhrData and then rest of ajax call process
// var xhr = new XMLHttpRequest();
// ... ... .... ... ...
【讨论】:
好的。我想我已经开始工作了。然而,问题 - 右下角的错误定位 - 仍然存在。如何解决? 您想在表单中显示 ReCaptcha 徽标吗?为此,您可以在grecaptcha.render()
中使用data-badge
属性或options.badge
选项。试试options.badge = "inline"
。内联后,您可以尝试应用自己的 CSS 来配置它。否则,您可以使用值 bottomright
将该图标移动到对角
这个答案很到位,做得很好,非常有用。
这比官方文档解释得更好,他们在解释渲染与执行方面做得不好。
我花了几个小时试图让不可见的验证码与我的 ajax 表单提交一起工作,但没有运气,但由于你的回答终于弄明白了。以上是关于不可见的 google Recaptcha 和 ajax 表单的主要内容,如果未能解决你的问题,请参考以下文章
Google reCAPTCHA 错误:提供的云项目编号不拥有给定的 reCAPTCHA 密钥
Google reCaptcha 2 TypeError:调用 grecaptcha.reset 后 a 为空