Skip to content

Instantly share code, notes, and snippets.

@feldpost
Forked from trevorturk/rack_honeypot.rb
Created May 1, 2009 23:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save feldpost/105327 to your computer and use it in GitHub Desktop.
Save feldpost/105327 to your computer and use it in GitHub Desktop.
# When a spammer wants to attack your site, they'll likely send an automated bot
# that will blindly fill out any forms it encounters. The idea of a "honeypot" is that
# you place a hidden field in a form. That's the honeypot. If this field is filled in, then
# it's almost certain to be a spammer (since a normal user wouldn't have even seen the
# field), and the contents of the form can safely be discarded.
# Normally, you would implement a "honeypot" in a Rails app with some combination of a
# special field in a particular form, and then some logic in the corresponding controller that
# would check for content in the "honeypot" field. This is somewhat of an inefficient
# approach, because it requires special code (not DRY), and bots are still going through an
# entire request/response cycle with all of the normal action/controller overhead.
# Using a Rack middleware strategy, you have a very low impact solution, both in terms of
# code needed, and in terms of impact on your servers. All you need to do is to enable the
# middleware and place a honeypot field in whatever forms you want to protect. Then, the middleware
# will return a blank 200 OK response for any form posts that include a value for the honeypot field.
# config/environment.rb
HONEYPOT_FIELD_NAME = 'something_unique_to_your_app'
config.middleware.use "Rack::Honeypot", HONEYPOT_FIELD_NAME
# lib/rack/honeypot.rb
module Rack
class Honeypot
def initialize(app, field_name)
@app = app
@field_name = field_name
end
def call(env)
form_hash = env["rack.request.form_hash"]
if form_hash && form_hash[@field_name] =~ /\S/
[200, {'Content-Type' => 'text/html', "Content-Length" => "0"}, []]
else
@app.call(env)
end
end
end
end
# app/views/posts/new.html.erb
<% form_for Post.new do |f| %>
<%= f.text_area :body %>
<div class="something_unique_to_your_app">
<%= label_tag HONEYPOT_FIELD_NAME, 'Please leave this field empty:' %>
<%= text_field_tag HONEYPOT_FIELD_NAME %>
</div>
<%= submit_tag 'Submit' %>
<% end %>
# public/stylesheets/application.css
# Replace HONEYPOT_FIELD_NAME with the name of your honeypot, as set in config/environment.rb
.HONEYPOT_FIELD_NAME { display: none; }
# That's it!
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment