A CAPTCHA is a challenge-response test used in applications to determine whether a human or a computer is interacting with the application. You've probably seen them — colorful images with distorted text at the bottom of Web registration forms. CAPTCHAs are used by many websites to prevent abuse from "bots," or automated programs usually written to generate spam. No computer program can read distorted text as well as humans can, so bots have a hard time navigating sites protected by CAPTCHAs.
This tutorial describes how to add a CAPTCHA challenge to your Force.com Site. It uses the popular reCAPTCHA technology to implement the challenge. This tutorial provides the source code for adding such a feature to your own applications.
To archive human knowledge and to make information more accessible to the world, multiple projects are currently digitizing physical books that were written before the computer age. The book pages are being photographically scanned, and then transformed into text using Optical Character Recognition (OCR). The transformation into text is useful because scanning a book produces images, which are difficult to store on small devices, expensive to download, and difficult to search. The problem is that OCR isn't perfect.
reCAPTCHA improves the process of digitizing books by sending words that can't be read by computers to the Web in the form of CAPTCHAs for humans to decipher. More specifically, each word that cannot be read correctly by OCR is placed on an image and used as a CAPTCHA.
Imagine creating a web site where you needed to ensure a human was responding. For example, you want to ensure that a human was filling in a form before creating a new account for them. You could do this by adding a CAPTCHA to the page, to challenge the user as shown in the following figure:
This article includes sample code, a Visualforce page with an associated Apex controller, that illustrates this in action — it tests your humanity. It's not a complete application, but it should give you the gist. Using the techniques from this tutorial you'll be able to code such CAPTCHAs into your own sites.
The following diagram can be found on the reCAPTCHA site, which I've included here for your reference.
As described in the reCAPTCHA API Documentation:
Enough of the theory, let's get to the practice!
Your first step is to sign up for a CAPTCHA key — you will need that in the code below. When I signed up for the key, I used the global key option.
Now you need to modify a few security settings in your environment. In particular, you need to enable callouts from Apex Code to a remote site. Our code does an
HTTP.send() to this site. To do this:
The figure above shows how we set it up for our developer environment.
I've created a simple helper class to use when implementing the reCAPTCHA. It's listed below. This code is free to use, under the new BSD open source license. Add your public and private key to this class by replacing the placeholders (see the first few lines) with the keys you got when you signed up for your reCAPTCHA account.
The key to this code is the
verify() method, which makes the HTTP POST to the reCAPTCHA site. Note that it stores the result of the challenge in the
Here's the Visualforce page. It will only test your humanity — it doesn't integrate with any other forms or input functionality. You'll have to integrate this source code into your own application as you see best. Normally you would pass your input elements in this same submit, and then inside the Apex code (in the method verify) you would perform the captcha and then take actions depending on the value of the boolean
In summary, this is an easy and fun project to add a human challenge-response system to your Force.com Sites input forms. It should dramatically reduce the amount of form spam you get.
On the do-it-yourself difficulty scale (1-easy, 5-complex), adding this feature to your application is about a 3 out of 5, only because you need to add your form fields in the correct place and then avoid creating records in your database if the
verified expression is false in your controller.