/invisible_captcha

:honey_pot: Unobtrusive and flexible spam protection for RoR apps

Primary LanguageRubyMIT LicenseMIT

Invisible Captcha

Gem Version Build Status

Simple and flexible spam protection solution for Rails applications. Based on the honeypot strategy to provide a better user experience.

Background

The strategy is based on adding an input field into the form that:

  • shouldn't be visible by the real users
  • should be left empty by the real users
  • will most be filled by spam bots

Installation

Add this line to you Gemfile:

gem 'invisible_captcha'

Or install the gem manually:

$ gem install invisible_captcha

Usage

There are different ways to implement, at Controller level or Model level:

Controller style

View code:

<%= form_tag(create_topic_path) do |f| %>
  <%= invisible_captcha %>
<% end %>

Controller code:

class TopicsController < ApplicationController
  invisible_captcha only: [:create, :update]
end

This method will act as a before_filter that triggers when spam is detected (honeypot field has some value). By default it responds with no content (only headers: head(200)). But you are able to define your own callback by passing a method to the on_spam option:

invisible_captcha only: [:create, :update], on_spam: :your_on_spam_callback_method

private

def your_on_spam_callback_method
  redirect_to root_path
end

Check here a complete list of allowed options.

Controller style (resource oriented):

In your form:

<%= form_for(@topic) do |f| %>
  <%= f.invisible_captcha :subtitle %>
  <!-- or -->
  <%= invisible_captcha :subtitle, :topic %>
<% end %>

In your controller:

invisible_captcha only: [:create, :update], honeypot: :subtitle

Model style

View code:

<%= form_for(@topic) do |f| %>
  <%= f.invisible_captcha :subtitle %>
<% end %>

Model code:

class Topic < ActiveRecord::Base
  attr_accessor :subtitle # define a virtual attribute, the honeypot
  validates :subtitle, :invisible_captcha => true
end

If you are using strong_parameters (by default in Rails 4), don't forget to keep the honeypot attribute into the params hash:

def topic_params
  params.require(:topic).permit(:subtitle)
end

Options and customization

This section contains a description of all plugin options and customizations.

Plugin options:

You can customize:

  • sentence_for_humans: text for real users if input field was visible.
  • error_message: error message thrown by model validation (only model implementation).
  • honeypots: collection of default honeypots, used by the view helper, called with no args, to generate the honeypot field name
  • visual_honeypots: make honeypots visible, also useful to test/debug your implementation.

To change these defaults, add the following to an initializer (recommended config/initializers/invisible_captcha.rb):

InvisibleCaptcha.setup do |config|
  config.sentence_for_humans = 'If you are a human, ignore this field'
  config.error_message       = 'You are a robot!'
  config.honeypots          += 'fake_resource_title'
  config.visual_honeypots    = false
end

Controller method options:

The invisible_captcha method accepts some options:

  • only: apply to given controller actions.
  • except: exclude to given controller actions.
  • honeypot: name of honeypot.
  • scope: name of scope, ie: 'topic[subtitle]' -> 'topic' is the scope.
  • on_spam: custom callback to be called on spam detection.

View helpers options:

Using the view/form helper you can override some defaults for the given instance. Actually, it allows to change: sentence_for_humans and visual_honeypots.

<%= form_for(@topic) do |f| %>
  <%= f.invisible_captcha :subtitle, visual_honeypots: true, sentence_for_humans: "Ei, don't fill on this input!" %>
  <!-- or -->
  <%= invisible_captcha visual_honeypots: true, sentence_for_humans: "Ei, don't fill on this input!" %>
<% end %>

Contribute

Any kind of idea, feedback or bug report are welcome! Open an issue or send a pull request.

Development

Clone/fork this repository and start to hack.

Run test suite:

$ rspec

Start a sample Rails app (source code) with InvisibleCaptcha integrated:

$ rake web # PORT=4000 (default: 3000)

License

Copyright (c) 2012-2015 Marc Anguera. Invisible Captcha is released under the MIT License.