You know, one of those pages which you can use to send an e-mail to the owners of the site.
Like most contact pages, it has only three fields:
- A 'From' field: the e-mail address of whomever is sending the mail (thank you Email::Valid for the validation :-))
- A 'Subject' field
- A 'Mail body' field
Long story short: It could end up costing me a bunch of money!
So, like any self respecting software developer would do, I set out on a glorious quest for a solution!
Five minutes later, I decided that I would add an "are you human"-type of validation via CAPTCHA.
I had heard about the different kinds of CAPTCHA's, and I surely also saw a lot of crappy ones!
After some more investigating, I started reading about reCAPTCHA.
All about reCAPTCHA
reCAPTCHA is very similar to any other type of CAPTCHA, except that it's not just a fixed list of images, or an image that's generated on the spot. No, reCAPTCHAs contains words from scanned books that couldn't be decoded by OCR software. This means that, every time you fill out a reCAPTCHA, you're actually helping in the digitizing of printed books! Isn't that great?!
Because of that, it's also free to use for any web developer, and it also has extra accessibility features:
People can choose to hear an audio recording that they then have to type out.
This way they can still fill out the reCAPTCHA, and they're helping in the digitizing of old time radio shows!
The first thing I was wondering was: "If the OCR software can't read the word correctly, then how do they know wether the submitted answer is correct or not?"
Luckily, the reCAPTCHA website explains this:
Each new word that cannot be read correctly by OCR is given to a user in conjunction with another word for which the answer is already known. The user is then asked to read both words. If they solve the one for which the answer is known, the system assumes their answer is correct for the new one. The system then gives the new image to a number of other people to determine, with higher confidence, whether the original answer was correct.
To start using reCAPTCHA you have to register on their site. (This is a one time and, as I already said, free registration). After registering, you get two keys: a private key and a public key.
The public key is used to retrieve a new CAPTCHA; The private key is then used (server-side) to validate the answer.
Implementing this in perl was trivial, because, as usual, the CPAN did not let me down and provides the fantastic Captcha::reCAPTCHA module! All I had to do, was try and make it work from a mojolicious application.
The synopsis of Captcha::reCAPTCHA looks like this:
On line 6, we notice that the module outputs html. That doesn't look very nice, but it's probably the only way to make it easy to use. This way, we don't need to know anything about the actual interface with reCAPTCHA.
But since it outputs html, it is clear that we'll need to make that call in our view template.
The easiest way to do that is by registering the get_html method as a helper in our mojolicious application:
Then we just call the helper from our template:
The %== (instead of the regular %=) indicates that the output of the reCAPTCHA helper must not be html escaped.
These four lines of code (of which two are just markup :-)) is enough to display the reCAPTCHA on our website.
Next step: validating the user's input. The Captcha::reCAPTCHA documentation states the following:
After the user has filled out the HTML form, including their answer for the CAPTCHA, use
check_answerto check their answer when they submit the form. The user's answer will be in two form fields, recaptcha_challenge_field and recaptcha_response_field. The reCAPTCHA library will make an HTTP request to the reCAPTCHA server and verify the user's answer.
That looks easy enough! Get two parameters and use them in a function call.
And really, apart from also passing the users's IP address (which we can easily fetch from the Mojo::Transaction object in the controller), that's all there's to it!
Ka-pow! we're done! We now have a reCAPTCHA protected contact page!