12

是否可以自定义 reCAPTCHA 表单参数(recaptcha_challenge_fieldrecaptcha_response_field)以便以不同方式调用它们?

基本上,我希望将表单参数recaptcha_challenge_field称为captchaId,并将recaptcha_response_field称为captchaUserResponse

我希望它们重命名,以便我可以抽象验证码实现......当请求到达时

发布 /mysite/userSignup

我不想打扰验证码的实现(reCaptcha,或者将来的其他东西)——为正确的验证码实现提取正确的参数,我想统一这些参数名称。

现在我的请求如下所示

POST /mysite/userSignup HTTP/1.1
Host: localhost:80
Connection: keep-alive
Content-Length: 416
Cache-Control: max-age=0
Origin: http://localhost:80
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.5 (KHTML, like Gecko) Chrome/19.0.1084.46 Safari/536.5
Content-Type: application/x-www-form-urlencoded
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Referer: http://localhost:8080/mysite/signup/form.html
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8,hr;q=0.6
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3

email:testUser%40gmail.com
username:testUser
password:test
password2:test
forename:Test
surname:User
recaptcha_challenge_field:<google generated challange>
recaptcha_response_field:<user typed captcha answer>
submit:Submit

但我希望它看起来像这样:

POST /mysite/userSignup HTTP/1.1
Host: localhost:80
Connection: keep-alive
Content-Length: 416
Cache-Control: max-age=0
Origin: http://localhost:80
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.5 (KHTML, like Gecko) Chrome/19.0.1084.46 Safari/536.5
Content-Type: application/x-www-form-urlencoded
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Referer: http://localhost:8080/mysite/signup/form.html
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8,hr;q=0.6
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3

email:testUser%40gmail.com
username:testUser
password:test
password2:test
forename:Test
surname:User
captchaId:<google generated challange>
captchaUserResponse:<user typed captcha answer>
submit:Submit

一种优雅的方法是指定这些表单参数名称,如下所示:

<script>
   var RecaptchaOptions = {
      recaptcha_challenge_field_formparam_name : 'captchaId',
      recaptcha_response_field_formparam_name: 'captchaUserResponse'
   };
</script>

如果这是不可能的,你建议什么解决方法?

4

6 回答 6

3

不需要额外的字段。您所要做的就是用 id 标识表单元素并在提交之前更改它们的相对名称。

假设您有以下表格:

<div id="captcha" class="item recaptcha">
...
<textarea id=custom1 name="recaptcha_challenge_field" rows="3" cols="40"></textarea>
<input id=custom2 name="recaptcha_response_field" value="manual_challenge" type="hidden" />
<input type="submit" name="submit" value="Submit">
</div>

您可以使用更改名称

document.captcha.custom1.name='captchaId'
document.captcha.custom2.name='captchaUserResponse'

这些更改可以使用 onclick 事件直接或间接(调用另一个方法)包含在提交按钮中。

因此,对于直接更改,您的提交将是:

<input type="submit" name="submit" value="Submit" onclick="document.captcha.custom1.name='captchaId';document.captcha.custom2.name='captchaUserResponse';return true">
于 2012-06-08T11:05:05.637 回答
3

由于 OP 尚未接受任何答案,因此我提供了这个答案。这正是 OP 在这篇文章的评论中寻找的确切内容:答案之一

创建一个 PHP 脚本并将其放在某处。我假设创建页面的 URI 是DESIRED_URI. 将此代码放入其中:

<?php
    header("Content-type: text/javascript");
    /*
    * These are the script parameters
    * You can change them by including desired ones in script's URL (as GET params)
    * challenge_field_original: original name of captcha challenge field
    * response_field_original: original name of captcha response field
    * to_challenge_field: the name of the challenge field you want
    * to_response_field: the name of the response field you want
    */
    $params = array(
        /*
        * Defining the defaults of the parameters
        */
        "challenge_field_original" => "recaptcha_challenge_field",
        "response_field_original" => "recaptcha_response_field",
        "to_challenge_field" => "captchaId",
        "to_response_field" => "captchaUserResponse",
    );
    /*
    * Checking for passed GET params to re-fill the parameters with non-default ones (if any)
    */
    if(isset($_GET['challenge']) && $_GET['challenge'] != "") {
        $params["to_challenge_field"] = $_GET['challenge'];
    }
    if(isset($_GET['response']) && $_GET['response'] != "") {
        $params["to_response_field"] = $_GET['response'];
    }
    if(isset($_GET['challenge_original']) && $_GET['challenge_original'] != "") {
        $params["challenge_field_original"] = $_GET['challenge_original'];
    }
    if(isset($_GET['response_original']) && $_GET['response_original'] != "") {
        $params["response_field_original"] = $_GET['response_original'];
    }
?>
/*
* I'm going to find the index of this script tag in the whole document
* So I can find its previous sibling node (the captcha form node)
*/
var scripts = document.getElementsByTagName( 'script' );
var thisScriptTag = scripts[ scripts.length - 1 ];

//now we have the index, good, I'm going to find its previous sibling node
var targetFormTag = (function(element) {
    if(typeof(element.previousElementSibling) == "undefined") {
        var p = element;
        do p = p.previousSibling;
        while (p && p.nodeType != 1);
        return p;
    } else {
        return element.previousElementSibling;
    }
})(thisScriptTag);

//Changing names...
(function(targetForm) {
    var a = targetForm.getElementsByTagName('input');
    var attr = '';
    var toAttr = '';
    for (var i in a) {
        try {
            attr = a[i].getAttribute('name')
        } catch(e) {
            continue;
        }
        switch(attr) {
            case '<?php echo $params["challenge_field_original"]; ?>':
            {toAttr='<?php echo $params["to_challenge_field"]; ?>';break;}
            case '<?php echo $params["response_field_original"]; ?>':
            {toAttr='<?php echo $params["to_response_field"]; ?>';break;}
        }
        a[i].setAttribute('name',toAttr);
    }
})(targetFormTag)

用法:

就像在表单后面包含脚本一样简单(!这非常重要!)。像这样:

<form><!--form elements--></form>
<script type="text/javascript" src="DESIRED_URI"></script>

您可以在一段时间后更改字段的名称,为此,请阅读代码文档。

旁注:

  • 该脚本可笑地跨浏览器(IE5+、Chrome、FF、Android)
  • 您可以将它用于任何验证码脚本,只需在脚本的src.
  • 该脚本尝试更改字段,失败时不会引发任何错误
于 2012-06-11T15:16:02.860 回答
3

这应该是不可能的。可能的解决方案 AFAIU 是添加新的 DOM 元素,这些元素在表单提交之前复制原始元素的值,例如:

<!-- the HTML part -->
<input type="hidden" id="captchaId">
<input type="hidden" id="captchaUserResponse">

// the JavaScript (jQuery) part
$('form').submit(function(){
  $('input#captchaId').
    val($('input#recaptcha_response_field').val());
  $('input#captchaUserResponse').
    val($('input#recaptcha_challenge_field').val());
  return true;
})
于 2012-06-01T05:18:05.553 回答
2

给你,我和你有同样的情况,这就是我的做法:

简短版:
在这里,将此属性添加到您的表单中,这就是您所需要的:

EDIT2 - 添加纯 Javascript 代码

纯 Javascript 方法
在 IE8、FF12 和 Chrome 上测试:

onsubmit="javascript:(function(p){var a=p.getElementsByTagName('input');var attr='';var toAttr='';for (var i in a){try {attr=a[i].getAttribute('name')} catch(e) {continue;}switch(attr){case 'recaptcha_challenge_field':{toAttr='captchaId';break;}case 'recaptcha_response_field':{toAttr='captchaUserResponse';break;}}a[i].setAttribute('name',toAttr);}p.submit();})(this)"

jQuery方法:

onsubmit="javascript:(function(p){var f=$(p);$('input[name=recaptcha_challenge_field]',f).attr('name','captchaId');$('input[name=recaptcha_response_field]',f).attr('name','captchaUserResponse');f.submit();})(this)"

例如:

<form method="post" action="verify.php" onsubmit="javascript:(function(p){var f=$(p);$('input[name=recaptcha_challenge_field]',f).attr('name','captchaId');$('input[name=recaptcha_response_field]',f).attr('name','captchaUserResponse');f.submit();})(this)">
    <?php
    require_once('recaptchalib.php');
    $publickey = "your_public_key"; // you got this from the signup page
    echo recaptcha_get_html($publickey);
    ?>
    <input type="submit" />
</form>

长版:
这是我正在做的事情:

1-这是负责替换输入名称的实际javascript函数,这里没什么特别的:

function(param){
    var form = $(param);
    $('input[name=recaptcha_challenge_field]',form).attr('name','captchaId');
    $('input[name=recaptcha_response_field]',form).attr('name','captchaUserResponse');
    form.submit();
}

2-我将把提到的函数设为匿名函数,这样我就可以通过内联 HTML 事件(onsubmit事件)调用它:

(function(param){...function code...})(this)
  • 注意到了(this)吗?在我们的匿名函数结束时?这样,我可以将表单的句柄传递给函数。

3-由于您需要尽可能少的客户端修改(或您所说的干预?),我将从 HTML 内联事件处理程序调用此匿名函数。在我们的例子中,最好的处理程序是onsubmit.

好吧,老实说,我自己很喜欢这个解决方案,希望它对你也有用:D

编辑1:

顺便说一句,我没有注意到你的评论,如果你想这样做的话:

<form><!--blah blah--></form>
<script type="text/js" src="somewhere"></script>

这些是缺点:

  1. 您正在添加一个额外的 HTTP 请求!为什么?
  2. 你使它与表单的 load-complete 事件异步,这使得它不准确
  3. 你有没有想过也许你的网络服务器在那个特定的时间拒绝了你客户的请求?那么会发生什么?它破坏了您的服务器端脚本!
  4. 如果您在服务器端打印表单,为什么不在服务器端进行这些更改?
于 2012-06-09T11:08:52.453 回答
2

您需要一种处理验证码的通用方式,因此,如果您决定使用 reCAPTCHA 以外的其他方法,您可以以同样的方式处理它。我觉得你的想法很好,但是你抽象的太深了。

理想情况下,您需要一些黑盒验证码系统,它只是做它的事情,而您不必担心盒子里有哪个验证码插件。您唯一需要摆脱该框的就是用户输入的内容是否正确。

如果您试图指示黑匣子如何进行此项检查,那么您就是在搞砸黑匣子。此外,如果您最终切换到不同的验证码插件,您也将不得不使用该插件。

由于这些原因,我建议你只抽象出一件事:一个is_human_user方法(或任何你想调用的方法)。您需要做的就是为您决定使用的每个验证码插件实现此方法。对于 reCAPTCHA,听起来这个方法会返回recaptcha_challenge_field == recaptcha_response_field. 然后,检查只是调用is_human_user什么,并且对实现是什么视而不见。

如果这不是您正在寻找的答案,我很抱歉,但退后一步并提醒自己为什么会陷入困境总是很重要的。

于 2012-06-13T23:40:35.583 回答
1

我相信你不能抽象太多的验证码实现,因为每个验证码都使用它自己的验证功能,无论如何更改客户端验证码字段的名称这不是最好的解决方案,因为如果客户端没有启用 JavaScript它根本行不通。

考虑到这一点,我认为抽象字段名称的最佳方法是在服务器端使用变量,在您收到表单的帖子后,您可以执行以下操作:

$captchaId = $_POST["recaptcha_challenge_field"];
$captchaUserResponse = $_POST["recaptcha_response_field"];

然后将它传递给一个通用的验证函数,如下所示:

recaptcha_generic_check ("PrivateKey", $_SERVER["REMOTE_ADDR"], $captchaId, $captchaUserResponse);

理想情况下,这样您只需要更改帖子中收到的字段的名称(当然还有功能),一切都将保持不变。

于 2012-06-11T23:53:49.393 回答