ReCaptcha 2.0与AJAX技术的整合

56

我已经成功将ReCaptcha 2.0应用到我的网站上。但是,只有在我不使用AJAX并允许表单“自然地”提交时才能正常工作。

我希望能够使用验证码提交表单,并通过成功提示而无需刷新页面来提醒用户。

我尝试了下面的代码,但似乎服务器没有收到用户的响应:

HTML:

<form class="form" action="javascript:void(0)" novalidate>
    <!-- all the inputs... -->

    <!-- captcha -->
    <div class="input-group">
        <div class="g-recaptcha" data-sitekey="6LdOPgYTAAAAAE3ltWQGar80KUavaR-JblgPZjDI"></div>
    </div>

    <div class="errors" id="errors" style="display: none"></div>

    <div class="input-group">
        <input type="button" value="Send" class="btn-default right" id="submit">
        <div class="clear"></div>
    </div>
</form>

JS:

$('#submit').click(function(e) {
    console.log('clicked submit'); // --> works

    var $errors = $('#errors'),
        $status = $('#status'),

        name = $('#name').val().replace(/<|>/g, ""), // prevent xss
        email = $('#email').val().replace(/<|>/g, ""),
        msg = $('#message').val().replace(/<|>/g, "");

    if (name == '' || email == '' || msg == '') {
        valid = false;
        errors = "All fields are required.";
    }

    // pretty sure the problem is here
    console.log('captcha response: ' + grecaptcha.getResponse()); // --> captcha response: 

    if (!errors) {
        // hide the errors
        $errors.slideUp();
        // ajax to the php file to send the mail
        $.ajax({
            type: "POST",
            url: "http://orenurbach.com/assets/sendmail.php",
            data: "email=" + email + "&name=" + name + "&msg=" + msg + "&g-recaptcha-response=" + grecaptcha.getResponse()
        }).done(function(status) {
            if (status == "ok") {
                // slide down the "ok" message to the user
                $status.text('Thanks! Your message has been sent, and I will contact you soon.');
                $status.slideDown();
                // clear the form fields
                $('#name').val('');
                $('#email').val('');
                $('#message').val('');
            }
        });
    } else {
        $errors.text(errors);
        $errors.slideDown();
    }
});

PHP:

<?php
    // assemble the message from the POST fields

    // getting the captcha
    $captcha = '';
    if (isset($_POST['g-recaptcha-response']))
        $captcha = $_POST['g-recaptcha-response'];
    echo 'captcha: '.$captcha;

    if (!$captcha)
        echo 'The captcha has not been checked.';
    // handling the captcha and checking if it's ok
    $secret = 'MY_SECRET';
    $response = json_decode(file_get_contents("https://www.google.com/recaptcha/api/siteverify?secret=".$secret."&response=".$captcha."&remoteip=".$_SERVER['REMOTE_ADDR']), true);

    var_dump($response);

    // if the captcha is cleared with google, send the mail and echo ok.
    if ($response['success'] != false) {
        // send the actual mail
        @mail($email_to, $subject, $finalMsg);

        // the echo goes back to the ajax, so the user can know if everything is ok
        echo 'ok';
    } else {
        echo 'not ok';
    }
?>

PHP页面中的结果:

captcha: The captcha has not been checked.array(2) { ["success"]=> bool(false) ["error-codes"]=> array(1) { [0]=> string(22) "missing-input-response" } } not ok

底线是,我如何手动获取输入响应而不让它自动与其余的POST数据一起发送?


在控制台中使用 grecaptcha.getResponse(),你得到了什么?是空的吗? - Samurai
@Samurai 是的。这就是为什么我认为问题在那里的原因。 - Gofilord
1
除非经过验证,否则它会返回空值(未回答或回答错误)。但是在验证之后,您应该会得到一个相当长的字符串。 - Samurai
@Samurai 你说得对,在控制台中我确实得到了那个字符串,但似乎服务器没有收到它。即使我检查过了,也会出现“missing-input-response”错误。 - Gofilord
如果在验证后将其发送到服务器,那么你不应该收到“验证码未经检查”的提示。 - Samurai
1个回答

25

好的,这有点儿愚蠢。

我做了一些错误的事情:

  • 在 PHP 文件中,所有字符串都使用单引号引起来,导致出现问题。
  • 在测试过程中,我在 PHP 文件中添加了多个打印输出,因此 if (status == "ok") 从未起作用。我确实收到了电子邮件,但没有得到任何确认,现在我知道为什么了。
  • 当我想要检查 PHP 文件省略了什么时,我只是在 URL 中输入其地址,总是会出错。即使邮件已经发送。现在我明白这不是检查日志的正确方法。

感谢 @Samurai 帮助我弄清楚事情。


最终 PHP 代码:

<?php
    // assemble the message from the POST fields

    // getting the captcha
    $captcha = "";
    if (isset($_POST["g-recaptcha-response"]))
        $captcha = $_POST["g-recaptcha-response"];

    if (!$captcha)
        echo "not ok";
    // handling the captcha and checking if it's ok
    $secret = "MY_SECRET";
    $response = json_decode(file_get_contents("https://www.google.com/recaptcha/api/siteverify?secret=".$secret."&response=".$captcha."&remoteip=".$_SERVER["REMOTE_ADDR"]), true);

    // if the captcha is cleared with google, send the mail and echo ok.
    if ($response["success"] != false) {
        // send the actual mail
        @mail($email_to, $subject, $finalMsg);

        // the echo goes back to the ajax, so the user can know if everything is ok
        echo "ok";
    } else {
        echo "not ok";
    }
?>

3
请问您能否提供最终的代码/标记,以便补充您自己的答案? - elmimmo
刚登录进来感谢你啊!顺便说一下,在 PHP 代码中,在 if 语句内第一个 echo "not ok"; 后面,你应该放置一个 exit; 命令。 - João Pimentel Ferreira
@joao_pimentel 为什么? - Gofilord
如果我理解正确的话,@Gofilord,如果客户端没有验证码响应,即!$captcha为真,则没有继续询问服务器的理由。 - João Pimentel Ferreira
2
在验证谷歌的响应时,使用!= false需要小心。在这里,使用== true同样有效且更安全。 - Goulash

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接