如何在单个页面上显示多个Recaptchas?


102

我在一页上有2个表格。其中一种形式具有始终显示的Recaptcha。另一个应仅在某些事件(例如,最大程度地尝试登录)后才显示recaptcha。所以有时候我需要2个Recaptchas才能出现在同一页面上。这可能吗?我知道我可能两者都可以使用一个,但是我有布局的方式,我更喜欢有2个。谢谢。

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

更新2:如果将每种表单放在iframe中怎么办?这是可以接受的解决方案吗?


您不能只显示两次相同的内容吗?
泰勒·卡特

1
我尝试了..当我尝试复制验证码时,它只会显示第一个验证码
oym

任何使用新的Recaptcha API的人都可以通过使用developer.google.com/recaptcha/docs/display#recaptcha_methods
El Yobo

3
与像in Hüseyin Yağlı的answer中那样使用JavaScript相比,iframe应该是可行的,但是是解决问题的一种不好的方法。大多数浏览器应支持JavaScript,并且默认的reCAPTCHA仍然使用JavaScript。我不知道如果没有JavaScript支持,需要做什么才能解决问题。
爱德华

Answers:


14

有人问过一个类似的问题,要在ASP页(链接)上执行此操作,并且在该处的共识是不可能使用Recaptcha来做。除非您愿意使用其他验证码,否则似乎一页上的多个表单必须共享验证码。如果您没有被限制在recaptcha中,那么Zend Frameworks Zend_Captcha组件(link)就是一个不错的库。它包含一些


9
实际上使用reCAPTCHA是可能的,但是如果没有JavaScript,就不可能做到。大多数浏览器应支持JavaScript,并且默认的ReCaptcha仍然使用JavaScript,因此此解决方案很好。Hüseyin Yağlı的答案说明了解决方案。有关此解决方案的reCAPTCHA文档,请访问developers.google.com/recaptcha/docs/display#explicit_render。我不知道如果没有JavaScript支持,需要做什么才能解决问题。
爱德华

实际上,使用reCAPTCHA绝对有可能
卡洛斯·埃斯皮诺萨

208

使用当前版本的Recaptcha(reCAPTCHA API版本2.0),您可以在一页上包含多个Recaptcha。

无需克隆Recaptcha或尝试解决此问题。您只需要为Recaptchas放置多个div元素,并在其中显式呈现Recaptchas。

使用Google recaptcha api可以轻松实现:https
//developers.google.com/recaptcha/docs/display#explicit_render

这是示例html代码:

<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脚本网址应如下所示:

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

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


1
巧合的是,您是否知道如何为每个字段添加隐藏的recaptcha字段以进行jquery验证?,目前我只能将其与1个recaptchafield一起使用,但可以与两个recaptchas一起使用吗?<input type =“ hidden” class =“ hiddenRecaptcha required” name =“ hiddenRecaptcha” id =“ hiddenRecaptcha”>
伊万·华雷斯

2
@IvanJuarez作为一个新问题,这是一个很好的问题。
侯赛因Yağlı

2
对于那些想要将grecaptcha.getResponse()与多个实例一起使用的人,您可以简单地将每个渲染引用为0、1,2等。例如,第一个实例将被引用为grecaptcha.getResponse(0)。
Gene Kelly

1
节省时间,这是完美的解决方案
Mirza Obaid

2
哇!这需要一些工作,但是要添加到@GeneKelly的注释中grecaptcha.getResponse(0)grecaptcha.getResponse(1)验证多个实例,我要补充一点,索引确实必须与grecaptcha.render顺序相对应 。对于此示例,grecaptcha.render('RecaptchaField1'...将通过进行验证, grecaptcha.getResponse(0)grecaptcha.render('RecaptchaField2'...通过grecaptcha.getResponse(1)等进行验证 ...
codacopia

75

简单明了:

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)现在调用它来遍历字段并创建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>

4
这是IMO的正确方法,这使它具有动态性,因为我可以拥有无​​限的实例而无需定义静态ID
Greg Alexander

1
如果您需要手动提取验证码(例如ajax请求中的内容),请查看我的答案
VanDir

你能看看我的问题吗?POST参数为空。
Marcio Mazzucato

3
data-sitekey="YOUR_KEY_HERE"是无用的,可以从div中删除(如果您需要更改键,则可以减少编辑的地方)
the_nuts

3
其实那里有错字。属性data-sitekey是必需的,并且在您有多个sitekey的情况下,即使需要,它也可以使其更加动态。正确的电话是grecaptcha.render(el, {'sitekey' : $(el).attr('data-sitekey') });
Gkiokan

13

使用jQuery的clone()功能可以轻松完成此操作。

因此,您必须为Recaptcha创建两个包装div。我的第一个表格的recaptcha 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));
});

可能不需要第二个参数中带有的trueclone(),但是拥有它不会有害...该方法的唯一问题是,如果您通过ajax提交表单,则问题是您有两个元素名称相同,并且您必须更聪明地捕获正确元素的值(reCaptcha元素的两个ID是#recaptcha_response_field和#recaptcha_challenge_field,以防万一有人需要它们)


当您请求新的挑战时,您将遇到问题,因为它将仅更新一个
Recaptcha

这不起作用...意味着仅原始的验证码(第一个称为<div id =“ myrecap”>的验证码)将被刷新,而其他未刷新
Oxi 2012年

实际上,奥西(Oxi),我先前的评论已解决了您的担忧
Serj Sagan 2012年

1
您可能做错了...在jsfiddle.net中链接到代码的方式怎么样,无论如何,不​​再需要执行任何此类操作...您应该使用HüseyinYağlı答案。
Serj Sagan

7

我知道这个问题很旧,但是万一将来有人找它的话。一页上可能有两个验证码。粉色的文档在这里: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>

5

这个答案是一个扩展@raphadko的答案

如果您需要手动提取验证码(例如在ajax请求中),则必须调用:

grecaptcha.getResponse(widget_id)

但是,如何检索小部件id参数?

我使用CaptchaCallback的此定义来存储每个g-recaptcha框的小部件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'));

提取代码。


1
嘿,谢谢你。什么是#your_recaptcha_box_id
卢卡斯·布斯塔曼特

4

我在页脚中有一个始终显示的联系表单,并且某些页面(例如“创建帐户”)也可以包含验证码,因此它是动态的,并且我正在使用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>

4

这是raphadkonoun提供的答案的无JQuery版本。

1)通常使用以下命令创建您的Recaptcha字段:

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

2)加载脚本:

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

3)现在调用它来遍历字段并创建Recaptchas:

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'});
    }
};

2

查看页面的源代码,我加入了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标签功能。因此,未包含该代码。

当用户单击“请求信息”时,(#product_tabs_what)JS将检查是否recapExistfalse或具有某些值。如果它有一个值,那么它将调用Recaptcha.destroy();以销毁旧的已加载的reCaptcha,并将为此选项卡重新创建它。否则,这只会​​创建一个reCaptcha并将其放入#more_info_recaptcha_boxdiv中。与“提供报价” #product_tabs_wha标签相同。


2

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>


2个表格部分在哪里?
MeSo2

抱歉,没有得到您
surinder singh

只是<div class="g-recaptcha" data-sitekey="your_site_key"></div>以表格/
格的

1

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

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

当用户提交以下表单之一时:

  1. 拦截提交-我使用了jQuery Form Plugin的beforeSubmit属性
  2. 销毁页面上任何现有的Recaptcha输入-我使用jQuery的$ .empty()方法和Recaptcha.destroy()
  3. 调用Recaptcha.create()为特定形式创建一个Recaptcha字段
  4. 返回false。

然后,他们可以填写验证码并重新提交表格。如果他们决定改为提交其他表单,那么您的代码将检查现有的Recaptcha,因此您一次只能在页面上获得一个Recaptcha。


1

要给raphadko的答案加一点点:由于(在一页上)有多个验证码,因此不能使用(通用)g-recaptcha-responsePOST参数(因为它仅包含一个验证码的响应)。相反,您应该grecaptcha.getResponse(opt_widget_id)对每个验证码使用call。这是我的代码(假设每个验证码都在其表单内):

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) + "\"}"

         });
    });
};

注意,我将事件委托(请参阅append element之后的刷新DOM)应用于所有动态修改的元素。这将每个个人captha的响应绑定到其form submit事件。


哇,我在找几个小时。谢谢!!
黑色

1

这是一个基于许多出色答案的解决方案。此选项是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>

1

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

每个reCAPTCHA都有自己的响应数据。您必须给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);

0

可以覆盖Recaptcha Ajax回调。可用的jsfiddle:http//jsfiddle.net/Vanit/Qu6kn/

您甚至不需要proxy 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");

0

这是完成此操作的不错指南:

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

基本上,您将一些参数添加到api调用中,并手动呈现每个Recaptcha:

<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:“ grecaptcha.render”方法收到一个ID


0

我会使用隐形的Recaptcha。然后在您的按钮上使用“ formname ='yourformname'”之类的标签来指定要提交的表单,并隐藏提交表单的输入。

这样做的好处是,您可以使html5表单验证保持完整,一次重新验证,但可以保留多个按钮界面。只需捕获由Recaptcha生成的令牌密钥的“验证码”输入值即可。

<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>

我发现此FAR更简单,更易于管理。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.