Using Recaptcha with AJAX in PHP

With bots getting intelligent enough to read easy versions of captcha, it’s time to make your site a little trickier if you want to avoid spam. This article will show you how to set up a PHP web form with AJAX that uses Recaptcha, a more difficult protocol for bots to decipher.

After a previous tutorial on PHP Ajax web forms, there were a lot of good points raised by the readers which could dramatically improve the usability and performance of any PHP AJAX web form validation. 

Any good PHP web form should be able to accomplish the following important objectives: 

1. The form validation should display all errors at once. The original web form discussed in the tutorial mentioned above can’t currently display all errors found in the PHP server side validation. As a result, it will only display a single error at a time. This is due to the use of the die () command. For example:

if ($countfirstname <2) {

echo ‘ERROR: You are using an invalid first name, it should contain more than one character.';

die ();

} 

 

The die () command terminates the execution of the PHP script and displays the error back to the browser. 

2. The captcha needs to be difficult. Modern bots have evolved to read easy captchas, according to Wikipedia. Fulfilling a need for a more challenging captcha like Recaptcha ( ) is important. 

3. Users should able to easily change wrong information entered into the form without needing to press the browser’s back button. This is where AJAX- enabled web forms are useful. 

4. Combining a PHP web form with AJAX validation means doing server-side validation of user inputs without the need for client validation like JavaScript (because AJAX itself is based in JavaScript). This eliminates the risk of spoofing common in-client validation.

Main requirements 

Unfortunately this type of Recaptcha AJAX in PHP will not work in all hosting accounts. It requires:

1. That an important PHP function for communicating with Recaptcha server be enabled. An example of this function includes Fopen. Typically these are disabled in free hosting accounts for security reasons. However, if you have a paid hosting account, then you need to find out if these are enabled by checking php.ini file.

2. A Recaptcha account for your own website. You should register it by signing up for Recaptcha for free. You need two important keys which you will get after signing up, and it is recommended that you copy these keys to a text file like notepad for your personal records. These keys are the Public Key and the Private Key. Without these important keys, your PHP web form using AJAX and Recaptcha will not work.

{mospagebreak title=Form design, planning and implementation} 

In a PHP AJAX environment, we need JavaScript files that will work along with the application. In this tutorial, we will use the prototype AJAX framework. All in all, we need to have the following files:

  • prototype.js: This is the default JavaScript framework needed for AJAX . A discussion of it is out of the scope of this article; you can refer to their website for details.
  • PHP Web form (index.php): This is the index.php file which will serve as an HTML form input for your users. In this form, you will need to integrate the prototype.js framework for AJAX as well as the Recaptcha.
  • Recaptcha library (recaptchalib.php): This is the PHP library file needed for recaptcha to work and communicate with their server. For a detailed discussion, refer to the Recaptcha developer website.
  • PHP validation script (ajaxvalidate.php): This is the actual PHP script that will do the actual PHP validation work.

All of these files are kept inside the same folder named “ajaxrecaptcha” so that it can be easily implemented with any server platform that is in compliance with the requirements. If you want to test this application inside an XAMPP local host, then the form URL will be: http://localhost/ajaxrecaptcha/ , or in a domain such as http://www.php-developer.org/ , the form URL accessible by the public will be located at http://www.php-developer.org/ajaxrecaptcha/ .

All naming convention of URLs use a relative URL structure for ease and flexibility of implementation on the part of the developer and the user.

If you want to implement this in your own website, aside from complying with the requirements stated earlier, you need to have your own folder name (for example, revising “ajaxrecaptcha” to “contact-me”). The folder naming in the script should also be revised, i.e. all references made to ajaxrecaptcha will be changed to “contact-me.” The rest of the structure and filenames stay the same.

Of course, you will be revising the field names to suit your own application (maybe for a guestbook, inquiry form, contact form, etc.).

{mospagebreak title=PHP web form scripting} 

The default web form will look like this:

 

For simplicity it asks for four pieces of information from the user: name, phone, age and the captcha input using Recaptcha. The explanation and process is basically similar to the previous AJAX web form  we discussed. 

However, since we are using Recaptcha, we will revise the old captcha from:

<img src="/ajaxwebform/captcha.php" />

<br />

Enter the Captcha as shown above:

<br /> <br />

<input style="background-color: #FFFFC0" type="text" name="captcha" id="captcha" size="10">

<br /> <br />

Into this script:

<?php

require_once(‘recaptchalib.php’);

$publickey = "***Your own website recaptcha public key here***";

echo recaptcha_get_html($publickey);

?>

The PHP recaptcha script to be added takes care of displaying the captcha image to the user. Since you are using PHP scripts, it is important that the file name extension uses .php rather than .htm or something else. You will need to add your own recaptcha public key and change the value of the $publickey variable:

$publickey = "4Ld1R3434343KJKJKJMGylVnGFGFGFz1R8NraDDDDDQW";

Finally, in the AJAX JavaScript code, you will also be sending the Recaptcha parameters via AJAX to the PHP validation script (ajaxvalidate.php). To add, we change the previous JavaScript code mentioned in the article from:

<script type="text/javascript">

function sendRequest() {

new Ajax.Request("/ajaxwebform/ajaxvalidate.php",

{

method: ‘post’,

parameters: ‘name=’+$F(‘name’)+’&phonenumber=’+$F(‘phonenumber’)+’&age=’+$F(‘age’)+’&captcha=’+$F(‘captcha’),

onComplete: showResponse

});

}

function showResponse(req){

$(‘show’).innerHTML= req.responseText;

}

</script>

Into this:

<script type="text/javascript">

function sendRequest() {

new Ajax.Request("/ajaxrecaptcha/ajaxvalidate.php",

{

method: ‘post’,

parameters: ‘name=’+$F(‘name’)+’&phonenumber=’+$F(‘phonenumber’)+’&age=’+$F(‘age’)+’&recaptcha_challenge_field=’+$F(‘recaptcha_challenge_field’)+’&recaptcha_response_field=’+$F(‘recaptcha_response_field’),

onComplete: showResponse

});

}

function showResponse(req){

$(‘show’).innerHTML= req.responseText;

}

</script>

 

Recaptcha variables are passed in the above AJAX parameters:

 … +’&recaptcha_challenge_field=’+$F(‘recaptcha_challenge_field’)+’&recaptcha_response_field=’+$F(‘recaptcha_response_field’),

 

These variables are recaptcha_challenge_field and recaptcha_response_field.

Those are the only changes made to the original AJAX web form. We will save this as index.php.

{mospagebreak title=PHP validation script: ajaxvalidate.php}

The first thing we need to check is the user’s captcha. Recaptcha developers  suggest this validation script:

 

<?php

require_once(‘recaptchalib.php’);

$errors=array();

$privatekey = "***Add your recaptcha private key here***";

$resp = recaptcha_check_answer ($privatekey,

                                $_SERVER["REMOTE_ADDR"],

                                $_POST["recaptcha_challenge_field"],

                                $_POST["recaptcha_response_field"]);

 

if (!$resp->is_valid) {
  die ("The reCAPTCHA wasn't entered correctly. Go back and try 
it again." .
       "(reCAPTCHA said: " . $resp->error . ")");
}

However, instead of terminating the script with die (), we will assign errors to a PHP array named $errors[] . With this approach we can dump all errors back to the users (along with field name error validation, not only the captcha) at once. So instead of having the die() command, we will have this:

if (!$resp->is_valid) {

  $errors[] = ‘ERROR: The recaptcha code was not entered correctly or expired. If you think it expired or correctly entered; click Recaptcha refresh button <img src="/ajaxrecaptcha/getanewchallenge.jpg" /> to get a new challenge and press submit again.';

}

If an error occurs, the text value error will be assigned to the array. The rest of the validation script follows the same principle as above. For example, in checking to see if the name, phone number and age fields are empty:

if (empty($name)) {

$errors[] = ‘ERROR: The name field is empty.';

}

if (empty($phonenumber)) {

$errors[] = ‘ERROR: The phone field is empty.';

}

if (empty($age)) {

$errors[] = ‘ERROR: The age field is empty.';

}

 

In the last part of the series of validation scripts, you need to determine how many errors are detected by the entire validation script. If there is no error, then proceed with the rest of the form processing (for example, displaying info back to the user, adding input to the MySQL database, etc). This can be accomplished using the PHP function sizeof(), which will count the number of entries in the array.

The script below does the actual work of dumping the errors back to the user:

if (sizeof($errors) > 0)

{

     echo "<ul>";

     foreach ($errors as $e)

     {

          echo "<li>$e</li>";

     }

     echo "</ul>";

     die ();

}

This code will be inserted after validation scripts:

<?php

 

/// Insert series of validation scripts here

 

if (sizeof($errors) > 0)

{

     echo "<ul>";

     foreach ($errors as $e)

     {

          echo "<li>$e</li>";

     }

     echo "</ul>";

     die ();

}

So for example, if mistakes are inputted in the form, it will display them all at once:

 

 

You can download the source code and see an actual working example.  

[gp-comments width="770" linklove="off" ]

chat