Tweetegy On the edge of chaos with Ruby, Rails, JavaScript and AngularJS.

| About | Search | Archive | Github | RSS |

Setting up a captcha with reCAPTCHA service and the captcha gem

We all know about captcha. It is a very common way to prevent spam from getting into your inbox, applications, databases, servers etc. It does this by displaying some slightly distorted text such that a machine is unlikely to interpret it correctly but a human will and this is the key. A captcha ensures that it is a real human filling out the form that will keep you busy!

reCAPTCHA

One of the best services to use for a captcha is Googles reCAPTCHA service. As usual, it's possible to use this service directly via it's API or use one of the many plugins or language wrappers available.

Since I am working on a Rails app, I will select one of the Ruby implementations. I opted for the Recaptcha Gem since the Rack Middleware based gem did not work on the Rails 2.x project I am working on at the moment.

Setup

Add the following to your gem file:

1 gem "recaptcha", :require => "recaptcha/rails"

Then register for a reCAPTCHA API key and add that to your environment config files:

1 #put this in development.rb and in production.rb (separate keys in each so you can test!)
2 RECAPTCHA_PUBLIC_KEY= 'your-public-key'
3 RECAPTCHA_PRIVATE_KEY= 'your-private-key'

The final step for setup is to add the following config file to your initializers directory:

1 #in config/initializers/recaptcha.rb
2 Recaptcha.configure do |config|
3   config.public_key  = RECAPTCHA_PUBLIC_KEY
4   config.private_key = RECAPTCHA_PRIVATE_KEY
5 end

View

The Captcha Gem provides helpers for your view to render the actual captcha box. It's as simple as putting the following into your view at the point where you wan the captcha to appear:

1 <%= raw recaptcha_tags %>

That's it for the view! Of course, this assumes you have put this tag into a form and that you already have error output etc. Moving on now to the server code (in the controller, of course!)

Controller Code

This is where the verification magic happens. The Captcha Gem provides another helper method that posts to the reCaptcha API server to check if what was submitted is correct. If it is then the method returns true, if not, it will add a custom error message that the captcha is wrong to the model instance. Here is the basic code as you might have it in the create action of your controller:

 1 #....model setup from params as usual...
 2 
 3 @model.valid? #ensures we see all errors on the model in the view if the captcha fails
 4   if verify_recaptcha(:model => @model, :message => "Please enter the correct captcha!")
 5     @model.save
 6     #all ok so do as you would normally
 7   else
 8     #model is not valid (that includes the captcha now! probably render the form again?
 9   end
10 
11 #...rest of create action

There are a few things happening here so let me explain. The first line to @model.valid? ensures that the models errors array is populated so that if the captcha is incorrect the user will see that message as well as all the model error validation messages. Without that only the captcha message is displayed if not entered correctly. It's nice to show the user all the errors in one go so to prevent server round trips.

The if statement then calls the verify_recaptcha helper which goes off to the Google reCAPTCHA server and validates the captcha has been enetered correctly or not. If not the message is added to the models errors array.

The rest of the controller action is as one would normally write it! So essentially one has replaced:

if @model.save ....

with

if verify_recaptcha(:model => @model, :message => "Please enter the correct captcha!") && @model.save

pretty neat and straightforward really!

Conclusion

Very easy to setup, configure and use thanks to the Google service and the well written Captcha Gem!