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
Add this line to you Gemfile:
gem 'invisible_captcha'
Or install the gem manually:
$ gem install invisible_captcha
There are different ways to implement, at Controller level or Model level:
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.
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
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
This section contains a description of all plugin options and customizations.
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 namevisual_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
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.
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 %>
Any kind of idea, feedback or bug report are welcome! Open an issue or send a pull request.
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)
Copyright (c) 2012-2015 Marc Anguera. Invisible Captcha is released under the MIT License.