Making a Simple Math Captcha using both jQuery and PHP

I wanted to write a simple Captcha that I could easily integrate into my own scripts that would work with or without Javascript. My first approach was to find open-source that I could pretty much just copy and paste into my code with little modification. All the cookie-cutter Captcha scripts I found were so bloated with extra code and were either only client-side (Javascript) or server-side (PHP), that I decided to create something from scratch. What I came up with is a script that uses Ajax for a smoother user experience (no browser reload on submit), but also works if the user has Javascript disabled for progressive enhancement (or graceful degradation).

Dependencies:  jQuery, jQuery Validation Plugin and jQuery Placeholder Plugin
Assumptions: Understands jQuery and PHP, and has used jQuery Validation Plugin. Note: this tutorial is written for developers and only explains the captcha portion. I don’t go into other workings of the form, ie: Ajax submit, error handling, etc.

Captcha Field

Simple addition captcha

The following code section goes into your HTML form to create the Captcha section. To set the values of the fields to be added, use PHP rand() function to get a different random value each time the page is loaded (1st number is random number 1-4, and 2nd number is random number from 5-9 for easy use).

<input id="num1" class="sum" type="text" name="num1" value="<?php echo rand(1,4) ?>" readonly="readonly" /> +
<input id="num2" class="sum" type="text" name="num2" value="<?php echo rand(5,9) ?>" readonly="readonly" /> =
<input id="captcha" class="captcha" type="text" name="captcha" maxlength="2" />
<span id="spambot">(Are you human, or spambot?)</span>
[divider_top]

Define custom method for Validation Plugin

Method basically gets the random values from the form, the total value entered by the user, adds them together and compares. If the two numbers don’t equal the total, then it returns an error. Otherwise it returns the result.

$.validator.addMethod('captcha',
function(value) {
$result = ( parseInt($('#num1').val()) + parseInt($('#num2').val()) == parseInt($('#captcha').val()) ) ;
$('#spambot').fadeOut('fast');
return $result;
},
'Incorrect value, please try again.'
);

Call custom validation method defined above

The highlighted sections are the relevant parts to the Captacha. The rest is doing error handling for the other form fields.


$('#contact').validate({
debug: false,
rules: {
message: {
required: true,
minlength: 10,
maxlength: 255
},
captcha: {
required: true,
captcha: true
}
},
messages: {
firstName: "First name field required.",
lastName: "Last name field required.",
email: {
required: "Email address required",
email: "Email address must be in the format name@domain.com."
},
message: {
required: "Message field required",
minlength: "Message must contain at least 10 characters.",
maxlength: "Message must not contain more than 255 characters."
},
chkCaptcha: {
required: "* Required"
}

}

});
[divider_top]

Server side handler (PHP) in case Javascript is disabled

Now we have to handle captcha if Javascript is disabled. Since the captcha values are generated using PHP, we can retrieve those from the POST array.

$num1 = isset($_POST['num1']) ? $_POST['num1'] : "";
$num2 = isset($_POST['num2']) ? $_POST['num2'] : "";
$total = isset($_POST['captcha']) ? $_POST['captcha'] : "";
[divider]

Define a Captcha function and call the function

function captcha_validation($num1, $num2, $total) {
global $error;
//Captcha check - $num1 + $num = $total
if( intval($num1) + intval($num2) == intval($total) ) {
$error = null;
}
else {
$error = "Captcha value is wrong.
";
}
return $error;
}

$captcha_error = captcha_validation($num1, $num2, $total);

Now Captcha can be validated with your other form variables. You can see a working demo here, or download it from the link below (contains all the code and dependent files).


Download from GitHub: https://github.com/laithsinawi/php-jquery-simple-math-captcha

This Post Has 35 Comments
  1. Great tut. Im trying to test this on my localhost and using wordpress but 2 things occur:

    1) the image seems to be broken
    2) when clicking Send it, i receive an Object Not Found error

    Any thoughts? I have placed all files and folders within my theme, so i assure you the process.php is where it needs to be. Thanks!

    1. Not sure. It sounds like a path issue. I don’t provide support, but if you post a link to your form, I can take a quick look.

      If you’re using WordPress, I’d suggest using a form plugin instead of trying to make this one work. Contact Form 7 is a great plugin, and it’s free. And it works well with Really Simple Captcha

  2. Thanks for doing this tutorial, just what I was looking for.

    As I am new to PHP, could give me a clue or explain how I would
    go about putting the errors on the same page as the form instead
    of echoing to another page.

    Thanks!

    1. Thanks James. The PHP error handling should only happen when Javascript is disabled, which I think is only about 2% of users. So having PHP error handling on a separate page shouldn’t be an issue. Otherwise, you could integrate process.php and index.php together as one file. You would also have to change the paths of the include files.

  3. Thanks Laith,

    As I said I am new to PHP and have to create three forms for my first
    website. I note that you use input fields to store the captcha values.
    Is this method safer than using an image created by a PHP script?
    Also, is it totally secure to include the form processing and the form as one page? While researching I think I remember an article saying
    the processing script is safer if it is in a separate file.

    Thanks.

    1. I put the captcha values in input fields purely for aesthetics. The input fields only show the values and don’t provide any functionality. I could’ve displayed the values in a div or anything.

      It’s probably correct that it’s more secure keeping your processing script in a separate file. This captcha was designed to be simple to implement and integrate into a form, and not designed with a secure captcha in mind. If you’re concerned about security, I’d suggest using something like Google’s ReCaptcha. It’s very secure and easy to implement with forms. http://www.google.com/recaptcha/captcha

      I don’t provide support and hope this helps.

  4. Hi there. Is this method secure? I think spambots nowadays can identify some values an input box very easily…

    1. You’re right, there’re probably some sophisticated bots out there than can figure it out, but I haven’t had any trouble. The input form fields don’t server any purpose, it’s purely aesthetics. You could put the values in divs or anything if that helps make it more secure. The purpose of this was to make it as simple as possible, so that it could easily integrate with other scripts or forms. If you’re looking for the most secure captcha, take a look at Google recaptcha. It uses image based characters that bots cannot read, and is fairly easy to implement. http://www.google.com/recaptcha

      1. Hey Dan – thanks for your post on how to bypass math captchas. I agree, simple math captchas are not secure, and your script shows how easy they are to figure out. Although, I think you can disabled get_file_contents via php.ini (allow_url_fopen directive), but I’m sure there’re other methods to use.

  5. Hello and thank you on this great script! I had a bit of problem using it because i put all your files into seperate folder(named php) in my root dir, and this form only work if everything is in root and not in some folder inside root.

  6. I found a solution i if you dont want to put files from this script to your root folder , but perhaps some other (i put everithing in php folder) you have to change several phats>

    1] change paths in your head for css, js to begin with you folder name (eg. php)
    etc.

    2] in your contat.php page change path too

    3] change contact.js file at line 83 to corespond your folder path too
    url: ‘php/process.php’,

    Maybe you should chane some more path idk i have working script now 😀

    1. Thanks Jovan. I’m glad you found it useful. I don’t really have the time to update the scripts, but if you want to post a link to your updated version and host it so people can download it, be my guest 🙂

  7. Thanks for a very useful tutorial.
    Just one question.
    How can I give attachment options for at least 3 files.
    User can attach 3 files with this form.

  8. Hello Laith!! Thank you so much for this plugin! I think its wonderful. I am having an issue though with the process file. When I click the Submit button to submit the form nothing happens. Everything appears to be set up correctly but I may be overlooking something. Thanks!

    1. Thanks Sabrina, I appreciate that. I can’t tell what the problem is without looking at your scripts which would require access to your website, but I don’t provide support. Does the form work independent from your website? You should be able to download, extract the zip, and run index.php to test it.

      1. Hey Laith! I have included another url in this reply message with the plugin uploaded independently and it still doesn’t work. Hopefully you can help. Thanks for your time! 🙂

        1. It looks like the sendMail function in process.php is failing. Did you set the mail function variables correctly? See process.php line numbers 12-14:

          // Change to appropriate settings
          define(‘TO’, ‘me@domain.com’);
          define(‘FROM’, ‘info@laithsinawi.com’);
          define(‘SUBJECT’, ‘Laith Sinawi Contact Form with Custom Captcha’);

  9. Great tutorial. I have been looking for a good math validation for a long time. One question, how would you get the email when sent out to actually echo the email of the person inputing the on the form? I have tried everything and all I get in the actual email is FROM: Name: sdafsdfas Message:nsajinspdanfsd etc…

    1. Yep, he completely plagiarized my post! Thanks for letting know. I’ll see what I can do to report to Google and maybe get his page banned from search results.

  10. Hey! I was wondering if once the form is submitted, instead of the “Message was sent successfully!” text displaying, can I simply redirect the user to another page? How would I do this?

    Adding this doesn’t work: header(‘Location: nextpage.php’);

    Hope you can help. Thanks! Great script!

Comments are closed.