A reader recently sent me a note saying he was trying to add CAPTCHA to his site. He had been trying to see how I used it in BlogCFC, and was just confused by what he saw. I thought I'd write a quick and simple guide for getting CAPTCHA on a form.
First - let's look at a simple form without CAPTCHA.
<cfparam name="form.email" default="">
<cfparam name="form.comments" default="">
<cfset showForm = true>
<cfif structKeyExists(form, "sendcomments")>
<cfset error = "">
<cfif not len(trim(form.name))>
<cfset error = error & "You must include your name, bozo.<br>">
<cfif not len(trim(form.email)) or not isValid("email", form.email)>
<cfset error = error & "Include a valid email address idiot!<br>">
<cfif not len(trim(form.comments))>
<cfset error = error & "It's called a Comment Form, stupid.<br>">
<cfif error is "">
<cfmail to="firstname.lastname@example.org" from="#form.email#" subject="Pointless comments from the public" wraptext="75">
From: #form.name# (#form.email#)
<cfset showForm = false>
<cfif structKeyExists(variables, "error")>
<b>Please correct these errors:<br>
<form action="test.cfm" method="post">
<td><input type="text" name="name" value="#form.name#"></td>
<td><input type="text" name="email" value="#form.email#"></td>
<td><input type="submit" name="sendcomments" value="Send Comments"></td>
Thank you for sending your comments, #form.name#.
I'm not going to say anything about this code as it's a fairly typical form. This will serve as a base form that we will be adding CAPTCHA too.
There are multiple CAPTCHA solutions out there, including the built-in support in BlueDragon and Alagad's CAPTCHA component. For this demo however I'm going to use the same product I used in BlogCFC, Lyla Captcha. This is a free product and is pretty simple to get up and running quickly. Download the product and unzip it to a folder. Any folder will do. Just make sure your application can access it.
The first thing we will do in our new form is to create an instance of the CFC:
<cfset application.captcha = createObject("component", "captchaService").init(configFile="captcha.xml") />
Lyla Captcha is configured via an XML file. You don't need to touch it immediately though. (Although I'll be pointing to a darn good blog entry about this XML file later on.)
Now we need to add the CAPTCHA to the form. I added a new row to my table with this code:
<td>Enter Text Shown in Picture:</td>
<input type="text" name="captcha"><br>
<!--- Captcha --->
<cfset captcha = application.captcha.createHashReference()>
<input name="hash" type="hidden" value="#captcha.hash#" />
There are a few things going on here. First off - I added a new text field so the user can type in the CAPTCHA text. I then ask Lyla to create a hash reference. This is a long, random string. I pass this to a CFM that will serve up an image. Lastly, I add the hash itself as a hidden form field.
Let's leave our form for a second and look at captcha.cfm:
<cfset variables.captcha = application.captcha.createCaptchaFromHashReference("stream",url.hash) />
<cfcontent type="image/jpg" variable="#variables.captcha.stream#" reset="false" />
I do a quick check to ensure the url variable exists, and then I simply use the Lyla Captcha built in functions to get the image data. (You can also store the CAPTCHA as a physical file.)
Now let's return back to the form. To validate the CAPTCHA, I simply call one more function in the CFC:
<cfset error = error & "You did not match the image text. Try again with half a brain.<br>">
That's it! Lyla is pretty trivial to use and you can't beat the price. Charlie Arehart also has a blog article on how to simplify the CAPTCHA text a bit - and I definitely recommend following his suggestions:
I've included all of my text files in the attachment to this blog entry. test.cfm is the original file and test2.cfm is the file with