如何在一个页面上显示多个重演?

我一页上有两张表格。其中一个窗体始终显示 Recaptcha。另一个应该显示一个 Recaptcha 后,只有在某个事件,如最大限度地登录尝试。所以有时候我需要2个 Recaptchas 出现在同一个页面上。这可能吗?我知道我可能会用一个单一的两个,但我的方式有布局,我更喜欢有2。谢谢。

更新: 好吧,我想这可能是不可能的。有人能推荐另一个与 reCaptcha 并行使用的捕获库吗?我真的希望能够有两个验证码在同一页面上。

Update 2: What if I put each form in an iframe? Would this be an acceptable solution?

151964 次浏览

关于在 ASP 页面(链接)上做这件事也有类似的问题,大家一致认为不可能使用重演技术。似乎一个页面上的多个表单必须共享验证码,除非您愿意使用不同的验证码。如果您没有被锁定在 captcha 中,那么一个很好的库可以查看 Zend 框架 Zend _ Captcha 组件(链接)。里面有一些

这可以通过 jQuery 的 clone()函数轻松实现。

因此,您必须为 captcha 创建两个包装 div:

<div id="myrecap">
<?php
require_once('recaptchalib.php');
$publickey = "XXXXXXXXXXX-XXXXXXXXXXX";
echo recaptcha_get_html($publickey);
?>
</div>

第二个表单的 div 是空的(不同的 ID) ,所以我的是:

<div id="myraterecap"></div>

那么 javascript 就很简单了:

$(document).ready(function() {
// Duplicate our reCapcha
$('#myraterecap').html($('#myrecap').clone(true,true));
});

可能不需要在 clone()中使用第二个带有 true值的参数,但是使用它也没有坏处... ... 这种方法的唯一问题是,如果你通过 ajax 提交表单,问题是你有两个具有相同名称的元素,你必须更聪明地捕获正确的元素的值(reCaptcha 元素的两个 id 是 #recaptcha_response_field和 # captcha _ Challenge _ field,以防有人需要它们)

一个不错的选择是为每个表单动态生成一个 captcha 输入(我已经用两个表单生成了这个输入,但是您可以生成三个或更多的表单)。我使用 jQuery、 jQuery 验证和 jQuery 表单插件通过 AJAX 和 Recaptcha AJAX API-发布表单

Https://developers.google.com/recaptcha/docs/display#recaptcha_methods

当用户提交其中一个表单时:

  1. 拦截提交-我使用了 jQuery Form Plugin 的 before Submit 属性
  2. 销毁页面上任何现有的重捕获输入-我使用了 jQuery 的 $. void ()方法和 Recaptcha.delete ()
  3. 调用 Recaptcha.create ()为特定的表单创建一个 captcha 字段
  4. return false.

然后,他们可以填写重演并重新提交表单。如果他们决定提交一个不同的表单,那么,您的代码将检查现有的重新捕捉,因此每次页面上只有一个重新捕捉。

查看页面的源代码时,我采用了 reCaptcha 部分,并稍微修改了代码。密码是这样的:

HTML:

<div class="tabs">
<ul class="product-tabs">
<li id="product_tabs_new" class="active"><a href="#">Detailed Description</a></li>
<li id="product_tabs_what"><a href="#">Request Information</a></li>
<li id="product_tabs_wha"><a href="#">Make Offer</a></li>
</ul>
</div>


<div class="tab_content">
<li class="wide">
<div id="product_tabs_new_contents">
<?php $_description = $this->getProduct()->getDescription(); ?>
<?php if ($_description): ?>
<div class="std">
<h2><?php echo $this->__('Details') ?></h2>
<?php echo $this->helper('catalog/output')->productAttribute($this->getProduct(), $_description, 'description') ?>
</div>
<?php endif; ?>
</div>
</li>


<li class="wide">
<label for="recaptcha">Captcha</label>
<div id="more_info_recaptcha_box" class="input-box more_info_recaptcha_box"></div>
</li>


<li class="wide">
<label for="recaptcha">Captcha</label>
<div id="make_offer_recaptcha_box" class="input-box make_offer_recaptcha_box"></div>
</li>
</div>

JQuery:

<script type="text/javascript" src="http://www.google.com/recaptcha/api/js/recaptcha_ajax.js"></script>
<script type="text/javascript">
jQuery(document).ready(function() {
var recapExist = false;
// Create our reCaptcha as needed
jQuery('#product_tabs_what').click(function() {
if(recapExist == false) {
Recaptcha.create("<?php echo $publickey; ?>", "more_info_recaptcha_box");
recapExist = "make_offer_recaptcha_box";
} else if(recapExist == 'more_info_recaptcha_box') {
Recaptcha.destroy(); // Don't really need this, but it's the proper way
Recaptcha.create("<?php echo $publickey; ?>", "more_info_recaptcha_box");
recapExist = "make_offer_recaptcha_box";
}
});
jQuery('#product_tabs_wha').click(function() {
if(recapExist == false) {
Recaptcha.create("<?php echo $publickey; ?>", "make_offer_recaptcha_box");
recapExist = "more_info_recaptcha_box";
} else if(recapExist == 'make_offer_recaptcha_box') {
Recaptcha.destroy(); // Don't really need this, but it's the proper way (I think :)
Recaptcha.create("<?php echo $publickey; ?>", "make_offer_recaptcha_box");
recapExist = "more_info_recaptcha_box";
}
});
});
</script>

我在这里使用的是简单的 javascript 选项卡功能。

When user would click on "Request Information" (#product_tabs_what) then JS will check if recapExist is false or has some value. If it has a value then this will call Recaptcha.destroy(); to destroy the old loaded reCaptcha and will recreate it for this tab. Otherwise this will just create a reCaptcha and will place into the #more_info_recaptcha_box div. Same as for "Make Offer" #product_tabs_wha tab.

这是可能的,只需覆盖 Recaptcha Ajax 回调

您甚至不需要代理 div,因为在覆盖的情况下,DOM 代码将无法执行。只要想再次触发回调,就可以调用 Recaptcha.reload ()。

function doSomething(challenge){
$(':input[name=recaptcha_challenge_field]').val(challenge);
$('img.recaptcha').attr('src', '//www.google.com/recaptcha/api/image?c='+challenge);
}


//Called on Recaptcha.reload()
Recaptcha.finish_reload = function(challenge,b,c){
doSomething(challenge);
}


//Called on page load
Recaptcha.challenge_callback = function(){
doSomething(RecaptchaState.challenge)
}


Recaptcha.create("YOUR_PUBLIC_KEY");

使用当前版本的 Recaptcha (ReCAPTCHA API 2.0版) ,您可以在一个页面上拥有多个 Recaptcha。

不需要克隆 Recaptcha,也不需要试图解决这个问题。您只需要为 Recaptchas 放置多个 <div>元素,并在其中显式地呈现 Recaptchas。

This is easy with Google Recaptcha API. Here is the example HTML code:

<form>
<h1>Form 1</h1>
<div><input type="text" name="field1" placeholder="field1"></div>
<div><input type="text" name="field2" placeholder="field2"></div>
<div id="RecaptchaField1"></div>
<div><input type="submit"></div>
</form>


<form>
<h1>Form 2</h1>
<div><input type="text" name="field3" placeholder="field3"></div>
<div><input type="text" name="field4" placeholder="field4"></div>
<div id="RecaptchaField2"></div>
<div><input type="submit"></div>
</form>

在 Javascript 代码中,必须为 Recaptcha 定义一个回调函数:

<script type="text/javascript">
var CaptchaCallback = function() {
grecaptcha.render('RecaptchaField1', {'sitekey' : '6Lc_your_site_key'});
grecaptcha.render('RecaptchaField2', {'sitekey' : '6Lc_your_site_key'});
};
</script>

之后,Recaptcha 脚本 URL 应该如下所示:

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

或者可以不给 Recaptcha 字段提供 ID,而是提供一个类名,并使用类选择器循环这些元素,然后调用 .render()

我知道这个问题很老了,但是以防将来有人会去找它。有可能在一页上有两个验证码。粉红色到文档在这里: < a href = “ https://developers.google.com/captcha/docs/display”rel = “ norefrer”> https://developers.google.com/recaptcha/docs/display 下面的例子只是一个复制表单文档,你不必指定不同的布局。

<script type="text/javascript">
var verifyCallback = function(response) {
alert(response);
};
var widgetId1;
var widgetId2;
var onloadCallback = function() {
// Renders the HTML element with id 'example1' as a reCAPTCHA widget.
// The id of the reCAPTCHA widget is assigned to 'widgetId1'.
widgetId1 = grecaptcha.render('example1', {
'sitekey' : 'your_site_key',
'theme' : 'light'
});
widgetId2 = grecaptcha.render(document.getElementById('example2'), {
'sitekey' : 'your_site_key'
});
grecaptcha.render('example3', {
'sitekey' : 'your_site_key',
'callback' : verifyCallback,
'theme' : 'dark'
});
};
</script>

简单明了:

  1. 使用以下命令正常创建 Recaptcha 字段:

    <div class="g-recaptcha" data-sitekey="YOUR_KEY_HERE"></div>
    
  2. 在脚本中加载以下内容:

    <script src="https://www.google.com/recaptcha/api.js?onload=CaptchaCallback&render=explicit" async defer></script>
    
  3. Now call this to iterate over the fields and create the Recaptchas:

    <script type="text/javascript">
    var CaptchaCallback = function() {
    jQuery('.g-recaptcha').each(function(index, el) {
    grecaptcha.render(el, {
    'sitekey' : jQuery(el).attr('data-sitekey')
    ,'theme' : jQuery(el).attr('data-theme')
    ,'size' : jQuery(el).attr('data-size')
    ,'tabindex' : jQuery(el).attr('data-tabindex')
    ,'callback' : jQuery(el).attr('data-callback')
    ,'expired-callback' : jQuery(el).attr('data-expired-callback')
    ,'error-callback' : jQuery(el).attr('data-error-callback')
    });
    });
    };
    </script>
    

我在页脚有联系人表单,总是显示,还有一些页面,像 Create Account,也可以有 captcha,所以它是动态的,我正在使用 jQuery 的下一种方式:

Html:

<div class="g-recaptcha" id="g-recaptcha"></div>


<div class="g-recaptcha" id="g-recaptcha-footer"></div>

Javascript

<script src="https://www.google.com/recaptcha/api.js?onload=CaptchaCallback&render=explicit&hl=en"></script>
<script type="text/javascript">
var CaptchaCallback = function(){
$('.g-recaptcha').each(function(){
grecaptcha.render(this,{'sitekey' : 'your_site_key'});
})
};
</script>

要向 Raphadko 的回答添加一点: 因为您有多个 captcha (在一个页面上) ,所以不能使用(通用的) g-recaptcha-response POST 参数(因为它只包含一个 captcha 的响应)。相反,您应该对每个验证码使用 grecaptcha.getResponse(opt_widget_id)调用。下面是我的代码(假设每个验证码都在它的表单中) :

HTML:

<form ... />


<div id="RecaptchaField1"></div>


<div class="field">
<input type="hidden" name="grecaptcha" id="grecaptcha" />
</div>


</form>

还有

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

JavaScript:

var CaptchaCallback = function(){
var widgetId;


$('[id^=RecaptchaField]').each(function(index, el) {


widgetId = grecaptcha.render(el.id, {'sitekey' : 'your_site_key'});


$(el).closest("form").submit(function( event ) {


this.grecaptcha.value = "{\"" + index + "\" => \"" + grecaptcha.getResponse(widgetId) + "\"}"


});
});
};

注意,我将事件委托(参见 在附加元素后刷新 DOM)应用于所有动态修改的元素。这将每个头状语的响应与其形式 submit事件绑定在一起。

var ReCaptchaCallback = function() {
$('.g-recaptcha').each(function(){
var el = $(this);
grecaptcha.render(el.get(0), {'sitekey' : el.data("sitekey")});
});
};
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://www.google.com/recaptcha/api.js?onload=ReCaptchaCallback&render=explicit" async defer></script>




ReCaptcha 1
<div class="g-recaptcha" data-sitekey="6Lc8WQcUAAAAABQKSITdXbc6p9HISCQhZIJwm2Zw"></div>


ReCaptcha 2
<div class="g-recaptcha" data-sitekey="6Lc8WQcUAAAAABQKSITdXbc6p9HISCQhZIJwm2Zw"></div>


ReCaptcha 3
<div class="g-recaptcha" data-sitekey="6Lc8WQcUAAAAABQKSITdXbc6p9HISCQhZIJwm2Zw"></div>

这里有一个很好的指南,可以帮助你做到这一点:

Http://mycodde.blogspot.com.ar/2014/12/multiple-recaptcha-demo-same-page.html

基本上,您可以向 api 调用添加一些参数,然后手动呈现每个概要:

<script src="https://www.google.com/recaptcha/api.js?onload=myCallBack&render=explicit" async defer></script>
<script>
var recaptcha1;
var recaptcha2;
var myCallBack = function() {
//Render the recaptcha1 on the element with ID "recaptcha1"
recaptcha1 = grecaptcha.render('recaptcha1', {
'sitekey' : '6Lc_0f4SAAAAAF9ZA', //Replace this with your Site key
'theme' : 'light'
});


//Render the recaptcha2 on the element with ID "recaptcha2"
recaptcha2 = grecaptcha.render('recaptcha2', {
'sitekey' : '6Lc_0f4SAAAAAF9ZA', //Replace this with your Site key
'theme' : 'dark'
});
};
</script>

PS: The "grecaptcha.render" method receives an ID

这个答案是 拉帕德科的回答的一个扩展。

如果您需要手动提取 captcha 代码(比如 Ajax 请求) ,您必须调用:

grecaptcha.getResponse(widget_id)

但是如何检索 widget id 参数呢?

我使用 回复的这个定义来存储每个 g-captcha 框的 小部件 ID(作为一个 HTML 数据属性) :

var CaptchaCallback = function() {
jQuery('.g-recaptcha').each(function(index, el) {
var widgetId = grecaptcha.render(el, {'sitekey' : 'your code'});
jQuery(this).attr('data-widget-id', widgetId);
});
};

然后我可以打电话:

grecaptcha.getResponse(jQuery('#your_recaptcha_box_id').attr('data-widget-id'));

来提取密码。

这里有一个建立在许多优秀答案基础上的解决方案。这个选项是免费的、动态的 jQuery,不需要您通过 id 专门定位元素。

1)像往常一样添加 reCAPTCHA 标记:

<div class="g-recaptcha" data-sitekey="YOUR_KEY_HERE"></div>

2)在文档中加入以下内容。它可以在任何支持 QuerySelectorAll API的浏览器中工作

<script src="https://www.google.com/recaptcha/api.js?onload=renderRecaptchas&render=explicit" async defer></script>
<script>
window.renderRecaptchas = function() {
var recaptchas = document.querySelectorAll('.g-recaptcha');
for (var i = 0; i < recaptchas.length; i++) {
grecaptcha.render(recaptchas[i], {
sitekey: recaptchas[i].getAttribute('data-sitekey')
});
}
}
</script>

这是 Raphadko名词提供的答案的无 JQuery 版本。

1)使用以下命令正常地创建概括查询字段:

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

2)加载脚本:

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

3)现在调用这个函数来遍历这些字段并创建重述:

var CaptchaCallback = function() {
var captchas = document.getElementsByClassName("g-recaptcha");
for(var i = 0; i < captchas.length; i++) {
grecaptcha.render(captchas[i], {'sitekey' : 'YOUR_KEY_HERE'});
}
};

我会用隐形的重现。然后在按钮上使用“ formname = ‘ yourformname’”这样的标记来指定要提交的表单并隐藏提交表单输入。

这样做的好处是允许您保持 html5表单验证的完整性,一个概要,但是多个按钮接口。只需捕获由 captcha 生成的令牌密钥的“ captcha”输入值即可。

<script src="https://www.google.com/recaptcha/api.js" async defer ></script>


<div class="g-recaptcha" data-sitekey="yours" data-callback="onSubmit" data-size="invisible"></div>
<script>
var formanme = ''
$('button').on('click', function () { formname = '#'+$(this).attr('formname');
if ( $(formname)[0].checkValidity() == true) { grecaptcha.execute(); }
else { $(formname).find('input[type="submit"]').click() }
});


var onSubmit = function(token) {
$(formname).append("<input type='hidden' name='captcha' value='"+token+"' />");
$(formname).find('input[type="submit"]').click()
};
</script>

我发现这个更简单,更容易管理。

grecaptcha.getResponse()方法接受一个可选的“ widget _ id”参数,如果未指定,则默认为第一个创建的 widget。对于创建的每个小部件 它与 reCAPTCHA 容器的属性 id无关! !,从 grecaptcha.render()方法返回 widget _ id

Each reCAPTCHA has its own response data. 您必须给 reCAPTCHA div 一个 ID,并将其传递给 getResponse方法:

例如:。

<div id="reCaptchaLogin"
class="g-recaptcha required-entry"
data-sitekey="<?php echo $this->helper('recaptcha')->getKey(); ?>"
data-theme="<?php echo($this->helper('recaptcha')->getTheme()); ?>"
style="transform:scale(0.82);-webkit-transform:scale(0.82);transform-origin:0 0;-webkit-transform-origin:0 0;">
</div>




<script type="text/javascript">
var CaptchaCallback = function() {
jQuery('.g-recaptcha').each(function(index, el) {
grecaptcha.render(el, {
'sitekey' : jQuery(el).attr('data-sitekey')
,'theme' : jQuery(el).attr('data-theme')
,'size' : jQuery(el).attr('data-size')
,'tabindex' : jQuery(el).attr('data-tabindex')
,'callback' : jQuery(el).attr('data-callback')
,'expired-callback' : jQuery(el).attr('data-expired-callback')
,'error-callback' : jQuery(el).attr('data-error-callback')
});
});
};
</script>


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

访问回复:

var reCaptchaResponse = grecaptcha.getResponse(0);

或者

var reCaptchaResponse = grecaptcha.getResponse(1);