This example is well out of date. Please don’t use it as is until I have a chance to update it.

I recently did some work for one of my clients that involved securing some simple web forms. These forms were to request literature or request a call back, simple stuff. Incidentally they were getting hammered with spam. The clients didn’t seem to care for this so they asked me to stop it.

My first move was to setup some sort of Captcha. I settled on reCaptcha and got to work on implementing it. I’d be on a bit of a jQuery kick lately so I wanted to see if I could validate the Captcha fields dynamically and only submit the form if they matched. It turned out that this was much easier than I’d thought.

To make this work, we’ll be using the following files:

  • recaptcha.php – The page that holds our form
  • ajax.recaptcha.php – The file that handles the ajax requests and outputs the result

Prerequisites

  1. The first thing we’ll do is setup our form. I’m going to assume you already have your form in place and that you are merely trying to secure it.
  2. Next, you’ll want to download the newest version of jQuery. You can put this file wherever you normally store your js files and include this in your page.
  3. Now it’s time to get yourself a reCaptcha keyset. A keyset is nothing more than a public and private key that allows you to use the reCaptcha service. It’s free. Head on over to http://recaptcha.net and click “Get reCaptcha” and fill out the necessary fields. Under domain, either fill out your site’s domain or set this up as a global key if you plan on using reCaptcha on multiple domains. Make a note of your public and private keys.

Now it’s time to put this all together. First we have to get our form to display our reCaptcha challenge field so the user can actually submit the form. My site uses PHP so I’ve downloaded the reCaptcha PHP Library and stored it on my server. At the top of my page, I have included this PHP file and setup my public and private keys. On this page, you really only need the public key, but I went ahead and included both so I don’t lose one of them. Here is what the top of my recaptcha.php looks like (with my keys blanked out):

recaptcha.php

require_once('/inc/recaptchalib.php');
$publickey = "XXXXXXXXXXXXXXXXXXXXXXXXXXXX"; // you got this from the signup page
$privatekey = "XXXXXXXXXXXXXXXXXXXXXXXXXXXX";

Next, you will include this in your page where you want the reCaptcha box to appear in the form:

recaptcha.php

echo recaptcha_get_html($publickey);

Next, we need to write our function that handles the dynamic/AJAX reCaptcha validation for us. I’ve done that already and you can see it below:

recaptcha.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
function validateCaptcha()
{
    challengeField = $("input#recaptcha_challenge_field").val();
    responseField = $("input#recaptcha_response_field").val();
    //alert(challengeField);
    //alert(responseField);
    //return false;
    var html = $.ajax({
    type: "POST",
    url: "ajax.recaptcha.php",
    data: "recaptcha_challenge_field=" + challengeField + "&recaptcha_response_field=" + responseField,
    async: false
    }).responseText;
 
    if(html == "success")
    {
        $("#captchaStatus").html(" ");
        // Uncomment the following line in your application
        return true;
    }
    else
    {
        $("#captchaStatus").html("Your captcha is incorrect. Please try again");
        Recaptcha.reload();
        return false;
    }
}

The above function grabs the reCaptcha data, submits it via a POST request to a file called ajax.recaptcha.php on our server, and waits for the repsonse. When it gets the response it either updates the status telling your user that the captcha didn’t match and then it reloads a new captcha for them, or it submits the form. The running demo code is slightly different to prevent the form from actually being submitted.

The last step to this part is to make sure your form runs this function when the user clicks that submit button. To do this, update the form’s opening tag and add an onsubmit event like this:

recaptcha.php

form name="loginform" id="loginform" action="#" method="post" onSubmit="return validateCaptcha()"

You’ll notice that we return true or false from the validateCaptcha() function. This controls if the form is submitted or not and is important for making this work.

Our final step in this process is to build the ajax.recaptcha.php file that we mentioned earlier to handle the requests. I’ve done this already and here is the final product (again with my keys blanked out):

ajax.recaptcha.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
require_once('/inc/recaptchalib.php');
$publickey = "XXXXXXXXXXXXXXXXXXXXXXXXXXXX"; // you got this from the signup page
$privatekey = "XXXXXXXXXXXXXXXXXXXXXXXXXXXX";
 
$resp = recaptcha_check_answer ($privatekey,
                                $_SERVER["REMOTE_ADDR"],
                                $_POST["recaptcha_challenge_field"],
                                $_POST["recaptcha_response_field"]);
 
if ($resp->is_valid) {
    ?>success< ?
}
else
{
    die ("The reCAPTCHA wasn't entered correctly. Go back and try it again." .
       "(reCAPTCHA said: " . $resp->error . ")");
}

This file outputs only the word “success” if the captcha matches and a message and the response from reCaptchta if it fails. This is important because we are looking for the word success in our validateCaptcha() function.

You can see the functioning demo for this or download a zip file of the files used in the demo including full PHP source code.