scambra / negative-captcha forked from subwindow/negative-captcha

A plugin to make the process of creating a negative captcha in Rails much less painless

This URL has Read+Write access

name age message
file LICENSE Tue Jun 10 20:40:13 -0700 2008 Hah. Copied license files are awesome. [Erik Peterson]
file README Loading commit data...
file Rakefile Sun Jun 01 10:01:22 -0700 2008 Initial commit [Erik Peterson]
file init.rb Sun Jun 01 10:01:22 -0700 2008 Initial commit [Erik Peterson]
directory lib/
file meta.yml Sun Jun 01 12:20:22 -0700 2008 Meta file [Erik Peterson]
directory test/ Mon Jun 30 09:10:25 -0700 2008 Fix test sourcing problem [Erik Peterson]
README
Negative Captcha Plugin
================ 

I.  What is a Negative Captcha?
  A negative captcha has the exact same purpose as your run-of-the-mill image captcha: To keep bots from submitting 
  forms.  Image ("positive") captchas do this by implementing a step which only humans can do, but bots cannot: read 
  jumbled characters from an image.  But this is bad.  It creates usability problems, it hurts conversion rates, and it 
  confuses the shit out of lots of people.  Why not do it the other way around? Negative captchas create a form that has 
  tasks that only bots can perform, but humans cannot.  This has the exact same effect, with (anecdotally) a much lower 
  false positive identification rate when compared with positive captchas.  All of this comes without making humans go 
  through any extra trouble to submit the form.  It really is win-win.
  
II.  How does a Negative Captcha Work?
  In a negative captcha form there are two main parts and three ancillary parts.  I'll explain them thusly.
  Main Part #1: Honeypots.
    Honeypots are form fields which look exactly like real form fields.  Bots will see them and fill them out.  Humans 
    cannot see them and thusly will not fill them out.  They are hidden indirectly- usually by positioning them off to 
    the left of the browser. They look kind of like this:
      <div style="position: absolute; left: -2000px;"><input type="text" name="name"  value="" /></div>
  Main Part #2: Real fields.
    These fields are the ones humans will see, will subsequently fill out, and that you'll pull your real form data out 
    of.  The form name will be hashed so that bots will not know what it is.  They look kind of like this:
      <input type="text" name="685966bd3a1975667b4777cc56188c7e" />
  Ancillary Part #1: Timestamp
    This is a field that is used in the hash key to make the hash different on every GET request, and to prevent 
    replayability.
  Ancillary Part #2: Spinner
    This is a rotating key that is used in the hash method to prevent replayability.  I'm not sold on its usefulness.
  Ancillary Part #3: Secret key
    This is simply some key that is used in the hashing method to prevent bots from backing out the name of the field 
    from the hashed field name.
    
III.  How does the Negative Captcha Plugin Work?
  1) Install the plugin:
    With Subversion
  script/plugin install http://code.subwindow.com/negative_captcha
    With git
  git submodule add git://github.com/subwindow/negative-captcha.git vendor/plugins/negative_captcha
  2) Add in the controller hooks
    #At top:
    before_filter :setup_negative_captcha, :only => [:new, :create]
    
    #At bottom:
    private
      def setup_negative_captcha
        @captcha = NegativeCaptcha.new(
          :secret => ::NEGATIVE_CAPTCHA_SECRET, #A secret key entered in environment.rb.  'rake secret' will give you a 
          good one.
          :spinner => request.remote_ip, 
          :fields => [:name, email, body], #Whatever fields are in your form 
          :params => params)
      end
  3) Modify your POST action(s) to check for the validity of the negative captcha form
    def create
      if @captcha.valid?
        @comment = Comment.create(@captcha.values) #Decrypted params
      end
      
      if @captcha.valid? && @comment.valid?
        redirect_to @comment
      else
        flash[:notice] = @captcha.error
        render :action => 'new'
      end
    end
  4) Modify your form to include the honeypots and other fields.  You can probably leave any select, radio, and check 
  box fields alone.  The text field/text area helpers should be sufficient.
    <% form_tag comments_path do -%>
      <%= negative_captcha(@captcha) %>
        <ul class="contact_us">
          <li>
              <label>Name:</label>
              <%= negative_text_field_tag @captcha, :name %>
          </li>
          <li>
              <label>Email:</label>
              <%= negative_text_field_tag @captcha, :email %>
          </li>
          <li>
              <label>Your Comment:</label>
              <%= negative_text_area_tag @captcha, :body %>
          </li>
          <li>
            <%= submit_tag %>
          </li>
        </ul>
      <% end -%>
  5) Test and enjoy!
  
IV. Possible Gotchas and other concerns
  - It is still possible for someone to write a bot to exploit a single site by closely examining the DOM.  This means 
  that if you are Yahoo, Google or Facebook, negative captchas will not be a complete solution.  But if you have a small 
  application, negative captchas will likely be a very, very good solution for you.  There are no easy work-arounds to 
  this quite yet.  Let me know if you have one.
  - I'm not a genius.  It is possible that a bot can figure out the hashed values and determine which forms are which.  
  I don't know how, but I think they might be able to.  I welcome people who have thought this out more thoroughly to 
  criticize this method and help me find solutions.  I like this idea a lot and want it to succeed.

V. Credit
  The idea for negative captchas is not mine.  It originates (I think) from Damien Katz of CouchDB.  
  I (Erik Peterson) wrote the plugin.  Calvin Yu wrote the original class which I refactored quite a bit and made into 
  the plugin.
  We did this while working on Skribit, an Atlanta startup (if you have a blog, please check us out at 
  http://skribit.com/)
  If you have any questions, concerns or have found any bugs, please email me at erik@skribit.com
  If you'd like to help improve or refactor this plugin, please create a fork on Github and let me know about it.  
  http://github.com/subwindow/negative-captcha