reCAPTCHA自定义表单参数名称

时间:2012-05-22 12:08:51

标签: javascript forms http captcha recaptcha

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

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

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

  

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

如果无法做到这一点,您建议使用哪种解决方法?

6 个答案:

答案 0 :(得分: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;
})

答案 1 :(得分:3)

由于OP尚未接受任何答案,我正在提供此答案。这正是OP在这篇文章的评论中所寻找的确切内容:one of the answers

创建一个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中提供原始输入的名称和该输入字段的所需名称。
  • 脚本尝试更改字段,失败时不会引发任何错误

答案 2 :(得分:2)

不需要额外的字段。您所要做的就是使用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">

答案 3 :(得分: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)"

E.G:

<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

<强> EDIT1:

顺便说一下,如果你想以这种方式做到这一点,我没有注意到你的意见:

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

这些是缺点:

  1. 您正在添加额外的HTTP请求!为什么呢?
  2. 你从表单的load-complete事件中使它异步,这使得它不准确
  3. 你有没有想过可能你的网络服务器,在那个特定时间,拒绝你客户的请求?那会发生什么?它打破了你的服务器端脚本!
  4. 如果您正在打印表单,服务器端,为什么不进行这些更改,服务器端?

答案 4 :(得分:2)

你想要一种处理验证码的通用方法,所以如果你决定使用reCAPTCHA之外的其他东西,你可以用同样的方式处理它。我认为你的思想很棒,但你的思想太过深刻。

理想情况下,您需要一些黑盒验证码系统才能完成它,您不必担心盒子中有哪个验证码插件。你需要离开那个盒子的唯一一件事就是用户是否输入了正确的东西。

如果您试图决定黑盒子如何进行此检查,那么您正在捣乱盒子。此外,如果你最终切换到另一个验证码插件,你也必须使用那个插件。

由于这些原因,我建议你只抽象出一件事:is_human_user方法(或任何你想要的方法)。您需要做的就是为您决定使用的每个captcha插件实现此方法。对于reCAPTCHA,听起来这个方法会返回recaptcha_challenge_field == recaptcha_response_field。然后,无论检查只是调用is_human_user,并且对实现的内容都是盲目的。

如果这不是您正在寻找的答案,我很抱歉,但重要的是退后一步并提醒自己为什么要打败那个兔子洞。

答案 5 :(得分:1)

我相信你不能抽象太多的验证码实现,因为每个验证码都使用它自己的验证函数,无论如何改变客户端的验证码字段的名称它不是最好的解决方案,因为如果客户端没有启用JavaScript后,它将无法正常工作。

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

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

然后将其传递给通用验证函数,如下所示:

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

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